OSI模型分層
OSI模型是指國際標准化組織(ISO)提出的開放系統互連參考模型(Open System Interconnection Reference Model,OSI/RM),它將網絡分為七層:物理層,數據鏈路層,網絡層,傳輸層,會話層,表示層,應用層
TCP/IP協議
TCP/IP是一系列網絡通信協議的統稱,其中最核心的兩個協議是TCP和IP。TCP稱為傳輸控制協議,IP稱為互聯網絡協議。
網絡分層除了OSI模型分層,還有TCP/IP模型分層,將網絡划分為四層,應用層、傳輸層、網際層、網絡接口層。TCP/IP模型分層是OSI模型分層的濃縮版
OSI模型和TCP/IP網絡分層的對應結構及TCP/IP部分協議族,
TCP三次握手
第一次握手:建立連接。客戶端發送連接請求報文段,將SYN位置為1,Sequence Number為x;然后,客戶端進入SYN_SEND狀態,等待服務器的確認;
第二次握手:服務器收到SYN報文段。服務器收到客戶端的SYN報文段,需要對這個SYN報文段進行確認,設置Acknowledgment Number為x+1(Sequence Number+1);同時,自己自己還要發送SYN請求信息,將SYN位置為1,Sequence Number為y;服務器端將上述所有信息放到一個報文段(即SYN+ACK報文段)中,一並發送給客戶端,此時服務器進入SYN_RECV狀態;
第三次握手:客戶端收到服務器的SYN+ACK報文段。然后將Acknowledgment Number設置為y+1,向服務器發送ACK報文段,這個報文段發送完畢以后,客戶端和服務器端都進入ESTABLISHED狀態,完成TCP三次握手。
三次握手圖解
JAVA Socket
Java使用ServerSocket(服務器端)和Socket(客戶端)進行基於TCP協議的網絡通信,服務器端痛過accetp()方法監聽客戶端連接。
雙方建立連接之后,可以通過socket對象的getInputStream和getOutputStream進行普通IO操作,雙方通信就和本地通信差不多。
下面是一個簡單的服務器端和客戶端通信的例子,
服務器端,
1 package network; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 import java.io.OutputStreamWriter; 8 import java.io.PrintStream; 9 import java.net.ServerSocket; 10 import java.net.Socket; 11 12 public class Server { 13 public static void main(String[] args) throws IOException { 14 //創建端口30000的服務器socket 15 ServerSocket ss = new ServerSocket(3500); 16 //在返回客戶端socket之前,accept將會一直阻塞 17 Socket s = ss.accept(); 18 BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); 19 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); 20 int i = 0; 21 while(true) { 22 //發送信息時,需要加上換行符,否則客戶端的readline()會阻塞 23 wr.write("你好,您收到服務器的新年祝福["+ i++ +"]\n"); 24 //使用flush方法可以立即清空buffer,讓消息馬上發出去,否則在buffer滿之前消息都不會發出去 25 wr.flush(); 26 27 String line = br.readLine(); 28 System.out.println("來自客戶端的數據:"+line); 29 } 30 } 31 }
客戶端,
1 package network; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 import java.io.OutputStreamWriter; 8 import java.net.Socket; 9 import java.net.UnknownHostException; 10 11 public class Client { 12 public static void main(String[] args) throws UnknownHostException, 13 IOException, InterruptedException { 14 Socket socket = new Socket("127.0.0.1", 3500); 15 BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 16 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); 17 int i = 0; 18 while (true) { 19 //發送信息時,需要加上換行符,否則服務器端的readline()會阻塞 20 wr.write("你好,您收到客戶端的新年祝福["+ i++ +"]\n"); 21 //使用flush方法可以立即清空buffer,讓消息馬上發出去,否則在buffer滿之前消息都不會發出去 22 wr.flush(); 23 24 String line = br.readLine(); 25 System.out.println("來自服務器的數據:" + line); 26 Thread.sleep(1000); 27 } 28 } 29 }
在cmd窗口中啟動服務器端, 之后打開一個新的cmd窗口,啟動客戶端,可以看到服務器端和客戶端互相發送和接受消息,執行結果如下,