基於TCP/IP協議的Socket程式設計
如今的大多數網路通訊都是選擇使用基於TCP/IP的協議進行,其中封裝的比較好的當屬socket了,下面就socket的使用進行詳細的描述:
一、Socket的工作模式
在TCP/IP網路應用中,通訊的兩個程序間相互作用的主要模式是客戶/伺服器(C/S)模式,即客戶向伺服器發出服務請求,伺服器接收到請求後,提供相應的服務。主要工作模式可以描述如下:
伺服器端:(首先伺服器要先啟動,伺服器根據請求提供相應服務)
(1)開啟一通訊通道並告知本地主機,它願意在某一公認地址上的某埠接收客戶請求;
(2)等待客戶請求到達該埠;
(3)接收到客戶端的服務請求時,處理該請求併發送應答訊號。當多工的伺服器接收到併發服務請求,會啟用一新程序來處理這個客戶請求。新程序處理此客戶請求,並不需要對其它請求作出應答。服務完成後,關閉此新程序與客戶的通訊鏈路,並終止。
(4)返回第(2)步,等待另一客戶請求。
(5)關閉伺服器
客戶端:
(1)開啟一通訊通道,並連線到伺服器所在主機的特定埠;
(2)向伺服器發服務請求報文,等待並接收應答;繼續提出請求
(3)請求結束後關閉通訊通道並終止。
二、工作原理
注:圖片來源於網路百度百科。
(1)建立連線(三次握手)
客戶端呼叫connect時,觸發了連線請求,向伺服器傳送資料包,然後connect進入阻塞狀態;伺服器監聽到連線請求呼叫accept函式接收請求向客戶端傳送確認資料包,然後accept進入阻塞狀態;客戶端收到伺服器的確認資料包之後connect返回,並對資料包進行確認;伺服器收到客戶端的資料包時accept返回,通過三次握手建立連線。
(2)進行通訊
伺服器根據客戶端的請求進行相應的應答。
(3)關閉連線(四次握手)
某個應用程序首先呼叫close主動關閉連線,這時TCP傳送一個結束訊號;伺服器接收訊號之後,執行被動關閉,
對這個訊號進行確認。伺服器傳送一個確認訊號給客戶端,接收到檔案結束符的應用程序呼叫close關閉它的socket,
最後向伺服器傳送一個確認訊號。
三、一個具體的例項實現伺服器和客戶端的通訊
伺服器:
客戶端:package connection; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; /** * Created with IntelliJ IDEA. * User: dsy * Date: 17-3-28 * Time: 上午9:44 * To change this template use File | Settings | File Templates. */ public class Server { public static void main(String args[]) throws IOException { int port = 5678; //定義一個ServerSocket監聽在埠5678上 ServerSocket server = new ServerSocket(port); while (true) { //server嘗試接收其他Socket的連線請求(阻塞式的) Socket socket = server.accept(); //接收到一個Socket就建立一個新執行緒來處理 new Thread(new Task(socket)).start(); } } /** * 用來處理Socket請求的 */ static class Task implements Runnable { private Socket socket; public Task(Socket socket) { this.socket = socket; } public void run() { try { handleSocket(); } catch (Exception e) { e.printStackTrace(); } } /** * 跟客戶端Socket進行通訊 */ private void handleSocket() throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); StringBuilder sb = new StringBuilder(); String temp; int index; while ((temp=br.readLine()) != null) { if ((index = temp.indexOf("end")) != -1) {//遇到end時就結束接收 sb.append(temp.substring(0, index)); break; } sb.append(temp); } System.out.println("receive from client: " + sb); //輸入傳送資訊 System.out.println(" send info:"); Writer writer = new OutputStreamWriter(socket.getOutputStream()); Scanner in = new Scanner(System.in); String s = in.nextLine(); writer.write(s); writer.write("end\n"); writer.flush(); writer.close(); br.close(); socket.close(); } } }
package connection;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
/**
* Created with IntelliJ IDEA.
* User: dsy
* Date: 17-3-28
* Time: 上午9:52
* To change this template use File | Settings | File Templates.
*/
public class Client {
public static void main(String args[]) throws Exception {
String host = "localhost"; //要連線的伺服器IP地址
int port = 5678; //要連線的伺服器埠號
//與伺服器建立連線
Socket client = new Socket(host, port);
//往服務端寫資料
System.out.println("Send info:");
Writer writer = new OutputStreamWriter(client.getOutputStream());
Scanner in = new Scanner(System.in);
String s = in.nextLine();
writer.write(s);
writer.write("end\n");
writer.flush();
//從伺服器接受資料
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
StringBuffer sb = new StringBuffer();
String temp;
int index;
while ((temp=br.readLine()) != null) {
if ((index = temp.indexOf("end")) != -1) {
sb.append(temp.substring(0, index));
break;
}
sb.append(temp);
}
System.out.println("receive from server: " + sb);
writer.close();
br.close();
client.close();
}
}