前言:如果覺得太長可以直接看實例,個人覺得協(xié)議就是一些人根據某些需求而共同達成的約定。
TCP(Transport Control Protocol)
面向連接的能夠提供可靠的流式數據傳輸的協(xié)議。類似于打電話的過程。
(URL、URLConnection、Socket、ServerSocket等類都使用TCP協(xié)議進行網絡通訊)

TCP通訊原理圖.png
TCP三次握手
所謂三次握手(Three-Way Handshake)即建立TCP連接,就是指建立一個TCP連接時,需要客戶端和服務端總共發(fā)送3個包以確認連接的建立。在socket編程中,這一過程由客戶端執(zhí)行connect來觸發(fā),整個流程如下圖所示:
- 第一次握手:Client將標志位SYN置為1,隨機產生一個值seq=J,并將該數據包發(fā)送給Server,Client進入SYN_SENT狀態(tài),等待Server確認。
- 第二次握手:Server收到數據包后由標志位SYN=1知道Client請求建立連接,Server將標志位SYN和ACK都置為1,ack=J+1,隨機產生一個值seq=K,并將該數據包發(fā)送給Client以確認連接請求,Server進入SYN_RCVD狀態(tài)。
- 第三次握手:Client收到確認后,檢查ack是否為J+1,ACK是否為1,如果正確則將標志位ACK置為1,ack=K+1,并將該數據包發(fā)送給Server,Server檢查ack是否為K+1,ACK是否為1,如果正確則連接建立成功,Client和Server進入ESTABLISHED狀態(tài),完成三次握手,隨后Client與Server之間可以開始傳輸數據了。
TCP四次握手(其實就是斷開TCP連接)
由于TCP連接時全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是當一方完成數據發(fā)送任務后,發(fā)送一個FIN來終止這一方向的連接,收到一個FIN只是意味著這一方向上沒有數據流動了,即不會再收到數據了,但是在這個TCP連接上仍然能夠發(fā)送數據,直到這一方向也發(fā)送了FIN。首先進行關閉的一方將執(zhí)行主動關閉,而另一方則執(zhí)行被動關閉。
- 第一次揮手:Client發(fā)送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態(tài)。
- 第二次揮手:Server收到FIN后,發(fā)送一個ACK給Client,確認序號為收到序號+1(與SYN相同,一個FIN占用一個序號),Server進入CLOSE_WAIT狀態(tài)。
- 第三次揮手:Server發(fā)送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態(tài)。
- 第四次揮手:Client收到FIN后,Client進入TIME_WAIT狀態(tài),接著發(fā)送一個ACK給Server,確認序號為收到序號+1,Server進入CLOSED狀態(tài),完成四次揮手。
UDP(User Datagram Protocol)
非面向連接的提供不可靠的數據包式的數據傳輸協(xié)議。類似于從郵局發(fā)郵件。
(DatagramPacket、DatagramSocket、MulticastSocket等類使用UDP協(xié)議進行網絡通訊)
比較:
TCP有建立時間
UDP傳輸有大小限制:64k以內
TCP的應用:Telnet(遠程登錄)、ftp(文件傳輸)
UDP的應用:ping命令
實例:
TCP通訊
//創(chuàng)建socket
Socket socket = new Socket("127.8.0.1",8080);
//創(chuàng)建輸出流
PrintWriter os =new PrintWriter(socket.getOutputStream());
//創(chuàng)建輸入流
BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
.....以下部分變成流的讀寫操作了......
......總結起來,建立連接之后其實變成了 I/O讀寫操作......
//###完成通訊之后關閉流###
// 關閉輸出流
os.close();
//關閉輸入流
is.close();
socket.close();
UDP通訊
###接收數據###
DatagramSocket socket =new DatagramSocket();
DatagramPacket packet =new DatagramPacket(buf,256);
buf:數據接收的對象 如:byte[] buf =new byte[256];
256:字節(jié)長度
用packet接收數據
socket.receive(packet);
//把數據轉字符串
String received =new String(packet.getData());
###發(fā)數據###
DatagramPacket packet =new DatagramPacket(buf,buf.length,address,port);
buf:數據發(fā)送的對象 如:byte[] buf =new byte[256];
buf.length:數據字節(jié)長度
address:發(fā)送的地址(比如:www.baidu.com或者192.168.9.2)
如:
InetAddress address = InetAddress.getByName("192.168.9.2");
port:端口號(如8080等)
發(fā)送packet數據
socket.send(packet);