Java中的TCP協議:
TCP協議提供面向連接的服務,通過它建立的是可靠地連接。Java爲TCP協議提供了兩個類:Socket類和ServerSocket類。
一個Socket實例代表了TCP連接的一個客戶端,而一個ServerSocket實例代表了TCP連接的一個服務器端,一般在TCP Socket編程中,客戶端有多個,而服務器端只有一個,客戶端TCP向服務器端TCP發送連接請求,服務器端的ServerSocket實例則監聽來自客戶端的TCP連接請求,併爲每個請求創建新的Socket實例,由於服務端在調用accept()等待客戶端的連接請求時會阻塞,直到收到客戶端發送的連接請求才會繼續往下執行代碼,因此要爲每個Socket連接開啓一個線程。服務器端要同時處理ServerSocket實例和Socket實例,而客戶端只需要使用Socket實例。另外,每個Socket實例會關聯一個InputStream和OutputStream對象,我們通過將字節寫入套接字的OutputStream來發送數據,並通過從InputStream來接收數據。
TCP連接的建立步驟:
客戶端向服務器端發送連接請求後,就被動地等待服務器的響應。典型的TCP客戶端要經過如下操作:
1、創建Socket連接服務端(指定ip地址,端口號)通過ip地址找對應的服務器,建立一個TCP連接;
2.通過Socket套接字的的getInputStream()和getOutputStream()方法獲取和服務端相連的IO流。輸入流可以讀取服務端輸出流寫出的數據,輸出流可以寫出數據到服務端的輸入流;
3、使用Socket類的close方法關閉連接。
服務端的工作是建立一個通信終端,並被動地等待客戶端的連接。典型的TCP服務端執行如下操作:
1、創建一個ServerSocket實例並指定本地端口,用來監聽客戶端在該端口發送的TCP連接請求;
2、重複執行:
1)調用ServerSocket的accept()方法以獲取客戶端連接,並通過其返回值創建一個Socket實例;
2)爲返回的Socket實例開啓新的線程,並調用Socket的getInputStream()和getOutputStream()方法獲取和客戶端相連的IO流,輸入流可以讀取客戶端輸出流寫出的數據,輸出流可以寫出數據到客戶端的輸入流;
3)通信完成後,使用Socket類的close()方法關閉該客戶端的套接字連接。
TCP Socket Demo:
客戶端代碼如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Demo_Client {
static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 12345);
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));//將字節流包裝成了字符流
PrintStream ps = new PrintStream(socket.getOutputStream());//PrintStream中有寫出換行的方法
System.out.println(br.readLine());
ps.println("中國的首都在哪?");
System.out.println(br.readLine());
ps.println("知道了");
socket.close();
}
}
服務端代碼如下:
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(12345);
while(true) {//不斷接受客戶端的請求
final Socket socket = server.accept();
new Thread() {
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));//將字節流包裝成了字符流
PrintStream ps = new PrintStream(socket.getOutputStream()); //PrintStream中有寫出換行的方法,所以用它
ps.println("百度一下,你就知道。");
System.out.println(br.readLine());
ps.println("北京");
System.out.println(br.readLine());
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}