JAVA——基於TCP/IP網路的文字聊天程式
阿新 • • 發佈:2018-12-12
基於TCP/IP網路的文字聊天程式
1.要求
使用JAVA完成一個基於TCP/IP網路的文字聊天程式,建立TCP客戶端套接字,分別為服務端和客戶端,並使兩端可以互聯。
2.TCP協議
在TCP協議中,有伺服器端(Server端)和客戶端(Client端)的概念。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) 伺服器端和客戶端關閉連線,釋放資源。
伺服器: 客戶端: