前言:如果覺得太長(zhǎng)可以直接看實(shí)例地熄,個(gè)人覺得協(xié)議就是一些人根據(jù)某些需求而共同達(dá)成的約定躏惋。
TCP(Transport Control Protocol)
面向連接的能夠提供可靠的流式數(shù)據(jù)傳輸?shù)膮f(xié)議校仑。類似于打電話的過程拙徽。
(URL彪标、URLConnection概而、Socket呼巷、ServerSocket等類都使用TCP協(xié)議進(jìn)行網(wǎng)絡(luò)通訊)
TCP三次握手
所謂三次握手(Three-Way Handshake)即建立TCP連接,就是指建立一個(gè)TCP連接時(shí)赎瑰,需要客戶端和服務(wù)端總共發(fā)送3個(gè)包以確認(rèn)連接的建立王悍。在socket編程中,這一過程由客戶端執(zhí)行connect來觸發(fā)餐曼,整個(gè)流程如下圖所示:
- 第一次握手:Client將標(biāo)志位SYN置為1压储,隨機(jī)產(chǎn)生一個(gè)值seq=J,并將該數(shù)據(jù)包發(fā)送給Server源譬,Client進(jìn)入SYN_SENT狀態(tài)集惋,等待Server確認(rèn)。
- 第二次握手:Server收到數(shù)據(jù)包后由標(biāo)志位SYN=1知道Client請(qǐng)求建立連接踩娘,Server將標(biāo)志位SYN和ACK都置為1刮刑,ack=J+1,隨機(jī)產(chǎn)生一個(gè)值seq=K养渴,并將該數(shù)據(jù)包發(fā)送給Client以確認(rèn)連接請(qǐng)求雷绢,Server進(jìn)入SYN_RCVD狀態(tài)。
- 第三次握手:Client收到確認(rèn)后理卑,檢查ack是否為J+1翘紊,ACK是否為1,如果正確則將標(biāo)志位ACK置為1藐唠,ack=K+1帆疟,并將該數(shù)據(jù)包發(fā)送給Server孵滞,Server檢查ack是否為K+1,ACK是否為1鸯匹,如果正確則連接建立成功坊饶,Client和Server進(jìn)入ESTABLISHED狀態(tài),完成三次握手殴蓬,隨后Client與Server之間可以開始傳輸數(shù)據(jù)了匿级。
TCP四次握手(其實(shí)就是斷開TCP連接)
由于TCP連接時(shí)全雙工的,因此染厅,每個(gè)方向都必須要單獨(dú)進(jìn)行關(guān)閉痘绎,這一原則是當(dāng)一方完成數(shù)據(jù)發(fā)送任務(wù)后,發(fā)送一個(gè)FIN來終止這一方向的連接肖粮,收到一個(gè)FIN只是意味著這一方向上沒有數(shù)據(jù)流動(dòng)了孤页,即不會(huì)再收到數(shù)據(jù)了,但是在這個(gè)TCP連接上仍然能夠發(fā)送數(shù)據(jù)涩馆,直到這一方向也發(fā)送了FIN行施。首先進(jìn)行關(guān)閉的一方將執(zhí)行主動(dòng)關(guān)閉,而另一方則執(zhí)行被動(dòng)關(guān)閉魂那。
- 第一次揮手:Client發(fā)送一個(gè)FIN蛾号,用來關(guān)閉Client到Server的數(shù)據(jù)傳送,Client進(jìn)入FIN_WAIT_1狀態(tài)涯雅。
- 第二次揮手:Server收到FIN后鲜结,發(fā)送一個(gè)ACK給Client,確認(rèn)序號(hào)為收到序號(hào)+1(與SYN相同活逆,一個(gè)FIN占用一個(gè)序號(hào))精刷,Server進(jìn)入CLOSE_WAIT狀態(tài)。
- 第三次揮手:Server發(fā)送一個(gè)FIN蔗候,用來關(guān)閉Server到Client的數(shù)據(jù)傳送鳄炉,Server進(jìn)入LAST_ACK狀態(tài)惯疙。
- 第四次揮手:Client收到FIN后,Client進(jìn)入TIME_WAIT狀態(tài),接著發(fā)送一個(gè)ACK給Server阱持,確認(rèn)序號(hào)為收到序號(hào)+1赴叹,Server進(jìn)入CLOSED狀態(tài)乱顾,完成四次揮手乍钻。
UDP(User Datagram Protocol)
非面向連接的提供不可靠的數(shù)據(jù)包式的數(shù)據(jù)傳輸協(xié)議。類似于從郵局發(fā)郵件庆寺。
(DatagramPacket蚊夫、DatagramSocket、MulticastSocket等類使用UDP協(xié)議進(jìn)行網(wǎng)絡(luò)通訊)
比較:
TCP有建立時(shí)間
UDP傳輸有大小限制:64k以內(nèi)
TCP的應(yīng)用:Telnet(遠(yuǎn)程登錄)懦尝、ftp(文件傳輸)
UDP的應(yīng)用:ping命令
實(shí)例:
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()));
.....以下部分變成流的讀寫操作了......
......總結(jié)起來知纷,建立連接之后其實(shí)變成了 I/O讀寫操作......
//###完成通訊之后關(guān)閉流###
// 關(guān)閉輸出流
os.close();
//關(guān)閉輸入流
is.close();
socket.close();
UDP通訊
###接收數(shù)據(jù)###
DatagramSocket socket =new DatagramSocket();
DatagramPacket packet =new DatagramPacket(buf,256);
buf:數(shù)據(jù)接收的對(duì)象 如:byte[] buf =new byte[256];
256:字節(jié)長(zhǎng)度
用packet接收數(shù)據(jù)
socket.receive(packet);
//把數(shù)據(jù)轉(zhuǎn)字符串
String received =new String(packet.getData());
###發(fā)數(shù)據(jù)###
DatagramPacket packet =new DatagramPacket(buf,buf.length,address,port);
buf:數(shù)據(jù)發(fā)送的對(duì)象 如:byte[] buf =new byte[256];
buf.length:數(shù)據(jù)字節(jié)長(zhǎng)度
address:發(fā)送的地址(比如:www.baidu.com或者192.168.9.2)
如:
InetAddress address = InetAddress.getByName("192.168.9.2");
port:端口號(hào)(如8080等)
發(fā)送packet數(shù)據(jù)
socket.send(packet);