1. 程式人生 > >JAVA——基於TCP/IP網路的文字聊天程式

JAVA——基於TCP/IP網路的文字聊天程式

基於TCP/IP網路的文字聊天程式

1.要求

使用JAVA完成一個基於TCP/IP網路的文字聊天程式,建立TCP客戶端套接字,分別為服務端和客戶端,並使兩端可以互聯。

2.TCP協議

在TCP協議中,有伺服器端(Server端)和客戶端(Client端)的概念。TCP傳輸資料的過程是:伺服器端程式在本機的某個埠上監聽,等待客戶端連線到此埠,一旦客戶端連線到了此埠,伺服器端和客戶端就可以進行資料傳輸了,資料傳輸結束後,關閉連線。下圖為TCP資料傳輸過程。 TCP資料傳輸過程

3.語法

在JAVA類庫中,與Socket相關的類都在java.net這個包中。InetAddress是代表IP地址的類,ServerSocket就是代表伺服器端的類,Socket是代表客戶端的類,同時也可以看作是代表連線的類,以下將對這三個類做一個簡單的介紹:

  • InetAddress類 InetAddress類的構造方法是私有的,所以我們不能夠通過new關鍵字來建立一個InetAddress類的例項。但是InetAddress類有幾個靜態方法,可以用於生成InetAddress的例項。我們在此處用到的就是getByAddress(byte[])這個靜態的方法。這個方法的引數是一個byte陣列。我們知道,一個IP地址是由4個位元組組成的,只要將這4個位元組順序放在一個byte陣列中,然後將它作為引數傳遞給這個方法,就可以得到一個IP地址。
  • ServerSocket類 ServerSocket類代表了伺服器端,根據圖19-5,它有以下幾個方法。 1)構造方法ServerSocket(int):引數是一個埠號,ServerSocket的例項創建出來後,會在指定的埠監聽。 2)accept():在指定的埠等待客戶端連線過來。在客戶端連線過來之前,當前執行緒是處於掛起狀態的,也就是說,如果沒有客戶端連線過來,這個方法不會執行結束。這個方法返回值是一個Socket型別的例項。 3)close():結束監聽,釋放資源。
  • Socket類 Socket類可以看做是兩個埠之間的連線。兩臺電腦之間的通訊使用的就是這個類。有兩種途徑來建立Socket類的例項。一種是前面說的,ServerSocket類的accpet()方法會返回一個Socket的例項;另一種是通過Socket類的構造方法建立。 這時候是通過Socket進行資料傳輸的,Socket類中主要的方法有以下幾個: 1) 構造方法Socket(InetAddress,int):指定Socket需要連線的遠端IP地址和埠。使用此構造方法創建出Socket例項,會連線到這個IP地址:埠號,並進一步可以使用這個IP地址:埠號進行資料傳輸。 2) getInputStream():方法返回值是一個InputStream的例項,通過輸入流可以讀取資訊。必須在建立連線後才能呼叫此方法。 3) getOutputStream():方法的返回值是一個OutputStream的例項,通過輸出流可以向遠端計算機輸入資訊。同樣,也必須在建立連線後才能呼叫此方法。 4) close():關閉連線,釋放資源。

4.服務端

  • 建立套接字描述符(socket)
  • 設定伺服器的IP地址和埠號(需要轉換為網路位元組序的格式)
  • 將套接字描述符繫結到伺服器地址(bind)
  • 將套接字描述符設定為監聽套接字描述符(listen),等待來自客戶端的連線請求,監聽套接字維護未完成連線佇列和已完成連線佇列
  • 從已完成連線佇列中取得隊首項,返回新的已連線套接字描述符(accept),如果已完成連線佇列為空,則會阻塞
  • 從已連線套接字描述符讀取來自客戶端的請求(read)
  • 向已連線套接字描述符寫入應答(write)
  • 關閉已連線套接字描述符(close),回到第5步等待下一個客戶端的連線請求

程式碼:

import java.io.BufferedReader;						// 引入需要使用的類
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class rw24 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			  ServerSocket ss = new ServerSocket(7777);
											// (1)在本機的7777埠監聽
			  System.out.println("伺服器端在7777埠監聽……"); 
			  Socket s = ss.accept();		// (2)等待客戶端連線到7777埠
			  // 如果沒有客戶端連線過來,accept()方法不會返回
			  System.out.println("已有客戶端連線過來,開始進行通訊……");
			  InputStream in = s.getInputStream();	// (3)得到輸入流
			  OutputStream out = s.getOutputStream();// (4)得到輸出流
			  PrintWriter pw = new PrintWriter(out);	
										// 使用PrintWriter向客戶端輸出資料
			  System.out.println("正在向客戶端傳送訊息……");
			  pw.write("客戶端,你好,這裡是伺服器端。\r\n");
			  pw.flush();				// 強制傳送資料
			  System.out.println("向客戶端傳送訊息完成。");
			  // 使用BufferedReader讀取客戶端傳送來的資料
			  BufferedReader br = new BufferedReader(new InputStreamReader(in));
			  String response = br.readLine();
			  System.out.println("\n======下面是客戶端發來的訊息======");
			  System.out.println(response);
			  System.out.println("================================");
			  br.close();					// (5)呼叫close()方法釋放資源
			  pw.close();
			  s.close();
			  ss.close();
		} catch (UnknownHostException e) {
			  System.out.println("無法找到相應的機器,錯誤資訊。" + e.getMessage());
		} catch (IOException e) {
			 System.out.println("資料傳輸出現異常:" + e.getMessage());
		}
	}

}

編譯結果如下圖所示: 在這裡插入圖片描述

5.客戶端

客戶端:

  • 建立套接字描述符(socket)
  • 設定伺服器的IP地址和埠號(需要轉換為網路位元組序的格式)
  • 請求建立到伺服器的TCP連線並阻塞,直到連線成功建立(connect)
  • 向套接字描述符寫入請求(write)
  • 從套接字描述符讀取來自伺服器的應答(read)
  • 關閉套接字描述符(close) urce=copy

程式碼:

import java.io.BufferedReader;					// 引入需要使用的類
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class rw25 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		byte[] addr = new byte[] { 127, 0, 0, 1 };		// 與本機進行通訊
		try {
			InetAddress local = InetAddress.getByAddress(addr);
			Socket s = new Socket(local, 7777);
			InputStream in = s.getInputStream();
			OutputStream out = s.getOutputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String response = br.readLine();
			System.out.println("======下面是服務端發來的訊息======");
			System.out.println(response);
			System.out.println("================================");
			System.out.println("正在向伺服器端傳送訊息……");
			PrintWriter pw = new PrintWriter(out);
			pw.write("伺服器你好,這裡是客戶端。");
			pw.flush();
			pw.close();
			br.close();
			s.close();
			System.out.println("向伺服器端傳送訊息結束。");
		} catch (UnknownHostException e) {
			System.out.println("無法找到相應的機器,錯誤資訊。" + e.getMessage());
		} catch (IOException e) {
			System.out.println("資料傳輸出現異常:" + e.getMessage());
		}

	}

}

在這裡插入圖片描述

6.文字聊天程式

  • 整個通訊的過程如下: 1) 伺服器監聽7777埠。 2) 客戶端連線伺服器端的7777埠。 3) 伺服器端向客戶端傳送資料。 4) 客戶端收到資料,輸出到控制檯。 5) 客戶端向伺服器端傳送資料。 6) 伺服器端收到資料並輸出到控制檯。 7) 伺服器端和客戶端關閉連線,釋放資源。

伺服器: 在這裡插入圖片描述 客戶端: 在這裡插入圖片描述