TCP的Java支持
協(xié)議相當(dāng)于相互通信的程序間達(dá)成的一種約定,它規(guī)定了分組報文的結(jié)構(gòu)、交換方式、包含的意義以及怎樣對報文所包含的信息進(jìn)行解析,TCP/IP協(xié)議族有IP協(xié)議、TCP協(xié)議和UDP協(xié)議?,F(xiàn)在TCP/IP協(xié)議族中的主要socket類型為流套接字(使用TCP協(xié)議)和數(shù)據(jù)報套接字(使用UDP協(xié)議)。
TCP協(xié)議提供面向連接的服務(wù),通過它建立的是可靠地連接。Java為TCP協(xié)議提供了兩個類:Socket類和ServerSocket類。一個Socket實例代表了TCP連接的一個客戶端,而一個ServerSocket實例代表了TCP連接的一個服務(wù)器端,一般在TCP Socket編程中,客戶端有多個,而服務(wù)器端只有一個,客戶端TCP向服務(wù)器端TCP發(fā)送連接請求,服務(wù)器端的ServerSocket實例則監(jiān)聽來自客戶端的TCP連接請求,并為每個請求創(chuàng)建新的Socket實例,由于服務(wù)端在調(diào)用accept()
等待客戶端的連接請求時會阻塞,直到收到客戶端發(fā)送的連接請求才會繼續(xù)往下執(zhí)行代碼,因此要為每個Socket連接開啟一個線程。服務(wù)器端要同時處理ServerSocket實例和Socket實例,而客戶端只需要使用Socket實例。另外,每個Socket實例會關(guān)聯(lián)一個InputStream和OutputStream對象,我們通過將字節(jié)寫入套接字的OutputStream來發(fā)送數(shù)據(jù),并通過從InputStream來接收數(shù)據(jù)。
TCP連接的建立步驟:
客戶端向服務(wù)器端發(fā)送連接請求后,就被動地等待服務(wù)器的響應(yīng)。典型的TCP客戶端要經(jīng)過下面三步操作:
1. 創(chuàng)建一個Socket實例:構(gòu)造函數(shù)向指定的遠(yuǎn)程主機和端口建立一個TCP連接;
2. 通過套接字的I/O流與服務(wù)端通信;
3. 使用Socket類的close方法關(guān)閉連接。
服務(wù)端的工作是建立一個通信終端,并被動地等待客戶端的連接。典型的TCP服務(wù)端執(zhí)行如下操作:
1. 創(chuàng)建ServerSocket對象,綁定并監(jiān)聽端口
2. 通過accept監(jiān)聽客戶端的請求
3. 建立連接后,通過輸出輸入流進(jìn)行讀寫操作
4. 關(guān)閉相關(guān)資源
一個程序為服務(wù)端,建立TCP服務(wù)端套接字。
java源程序如下:
import java.io.DataInputStream;//導(dǎo)入DataInputStream類import java.io.DataOutputStream;//導(dǎo)入DataOutputStreamimport java.io.IOException;//導(dǎo)入IOException類import java.net.Socket;//導(dǎo)入Socket類import java.util.Scanner;//導(dǎo)入Scanner類/** * 注意用到的輸入輸出流DataInputStream和DataOutputStream,成對出現(xiàn),最好用字節(jié)流 */// 客戶端類public class ChatClient {//創(chuàng)建公共類 private String host = 'localhost';// 默認(rèn)連接到本機 private int port = 8189;// 默認(rèn)連接到端口8189 public ChatClient() { } // 連接到指定的主機和端口 public ChatClient(String host, int port) {//構(gòu)造方法 this.host = host;//將構(gòu)造方法的參數(shù)host傳遞給類變量host this.port = port;//將構(gòu)造方法的參數(shù)port傳遞給類變量port } public void chat() {//chat方法 try { // 連接到服務(wù)器 Socket socket = new Socket(host, port);//創(chuàng)建Socket類對象 try { DataInputStream in = new DataInputStream(socket .getInputStream());// 讀取服務(wù)器端傳過來信息的DataInputStream DataOutputStream out = new DataOutputStream(socket .getOutputStream());// 向服務(wù)器端發(fā)送信息的DataOutputStream Scanner scanner = new Scanner(System.in);// 裝飾標(biāo)準(zhǔn)輸入流,用于從控制臺輸入 while (true) { String send = scanner.nextLine();//讀取控制臺輸入的內(nèi)容 System.out.println('客戶端:' + send);//輸出鍵盤輸出內(nèi)容提示 ,也就是客戶端向服務(wù)器端發(fā)送的消息 // 把從控制臺得到的信息傳送給服務(wù)器 out.writeUTF('客戶端:' + send);//將客戶端的信息傳遞給服務(wù)器 String accpet = in.readUTF();// 讀取來自服務(wù)器的信息 System.out.println(accpet);//輸出來自服務(wù)器的信息 } } finally { socket.close();//關(guān)閉Socket監(jiān)聽 } } catch (IOException e) {//捕獲異常 e.printStackTrace(); } } public static void main(String[] args) {//主程序方法 new ChatClient().chat();//調(diào)用chat方法 }}
另外一個程序為客戶端,建立TCP客戶端套接字。
java源程序如下:
import java.io.DataInputStream; //導(dǎo)入 DataInputStream類import java.io.DataOutputStream;//導(dǎo)入DataOutputStream類 import java.io.IOException;//導(dǎo)入IOException類import java.net.ServerSocket;//導(dǎo)入ServerSocket類 import java.net.Socket; //導(dǎo)入Socket 類 import java.util.Scanner; //導(dǎo)入Scanner類/** * 模擬qq聊天功能: 實現(xiàn)客戶端與服務(wù)器(一對一)的聊天功能,客戶端首先發(fā)起聊天,輸入的內(nèi)容在服務(wù)器端和客戶端顯示, * 然后服務(wù)器端也可以輸入信息,同樣信息也在客戶端和服務(wù)器端顯示 */ // 服務(wù)器類 public class ChatServer {//ChatServer類 private int port = 8189;// 默認(rèn)服務(wù)器端口 public ChatServer() { } // 創(chuàng)建指定端口的服務(wù)器 public ChatServer(int port) {//構(gòu)造方法 this.port = port;//將方法參數(shù)賦值給類參數(shù) } // 提供服務(wù) public void service() {//創(chuàng)建service方法 try {// 建立服務(wù)器連接 ServerSocket server = new ServerSocket(port);//創(chuàng)建 ServerSocket類 Socket socket = server.accept();// 等待客戶連接 try { DataInputStream in = new DataInputStream(socket .getInputStream());// 讀取客戶端傳過來信息的DataInputStream DataOutputStream out = new DataOutputStream(socket .getOutputStream());// 向客戶端發(fā)送信息的DataOutputStream Scanner scanner = new Scanner(System.in);//從鍵盤接受數(shù)據(jù) while (true) { String accpet = in.readUTF();// 讀取來自客戶端的信息 System.out.println(accpet);//輸出來自客戶端的信息 String send = scanner.nextLine();//nextLine方式接受字符串 System.out.println('服務(wù)器:' + send);//輸出提示信息 out.writeUTF('服務(wù)器:' + send);//把服務(wù)器端的輸入發(fā)給客戶端 } } finally {// 建立連接失敗的話不會執(zhí)行socket.close(); socket.close();//關(guān)閉連接 server.close();//關(guān)閉 } } catch (IOException e) {//捕獲異常 e.printStackTrace(); } } public static void main(String[] args) {//主程序方法 new ChatServer().service();//調(diào)用 service方法 } }
注:在運行前要建立兩個控制臺窗口
運行結(jié)果如下: