日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java TCP/UDP socket 编程流程总结

發(fā)布時(shí)間:2025/4/16 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java TCP/UDP socket 编程流程总结 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

????最近正好學(xué)習(xí)了一點(diǎn)用java socket編程的東西。感覺(jué)整體的流程雖然不是很繁瑣,但是也值得好好總結(jié)一下。

Socket

? ? Socket可以說(shuō)是一種針對(duì)網(wǎng)絡(luò)的抽象,應(yīng)用通過(guò)它可以來(lái)針對(duì)網(wǎng)絡(luò)讀寫數(shù)據(jù)。就像通過(guò)一個(gè)文件的file handler就可以都寫數(shù)據(jù)到存儲(chǔ)設(shè)備上一樣。根據(jù)TCP協(xié)議和UDP協(xié)議的不同,在網(wǎng)絡(luò)編程方面就有面向兩個(gè)協(xié)議的不同socket,一個(gè)是面向字節(jié)流的一個(gè)是面向報(bào)文的。

? ? ?對(duì)socket的本身組成倒是比較好理解。既然是應(yīng)用通過(guò)socket通信,肯定就有一個(gè)服務(wù)器端和一個(gè)客戶端。所以它必然就包含有一個(gè)對(duì)應(yīng)的IP地址。另外,在這個(gè)地址上server要提供一系列的服務(wù),于是就需要有一系列對(duì)應(yīng)的窗口來(lái)提供服務(wù)。所以就有一個(gè)對(duì)應(yīng)的端口號(hào)(Port)。端口號(hào)是一個(gè)16位的二進(jìn)制數(shù)字,那么范圍就是從(0-65535)。IP地址加端口號(hào)基本上就構(gòu)成了socket。下面這幅圖可以描繪出socket和整個(gè)TCP/IP之間的關(guān)系:



TCP

? ? TCP主要是面向連接的協(xié)議,它包含有建立和拆除連接,保證數(shù)據(jù)流的順序和正確性等功能。每次對(duì)TCP中間的數(shù)據(jù)操作相當(dāng)于對(duì)一個(gè)數(shù)據(jù)流進(jìn)行訪問(wèn)。它最典型的特征就是那三次握手的建立連接過(guò)程。TCP的連接建立和撤銷過(guò)程如下圖:

Server端

Server端所要做的事情主要是建立一個(gè)通信的端點(diǎn),然后等待客戶端發(fā)送的請(qǐng)求。典型的處理步驟如下:

1. 構(gòu)建一個(gè)ServerSocket實(shí)例,指定本地的端口。這個(gè)socket就是用來(lái)監(jiān)聽(tīng)指定端口的連接請(qǐng)求的。

2.重復(fù)如下幾個(gè)步驟:

a. 調(diào)用socket的accept()方法來(lái)獲得下面客戶端的連接請(qǐng)求。通過(guò)accept()方法返回的socket實(shí)例,建立了一個(gè)和客戶端的新連接。

b.通過(guò)這個(gè)返回的socket實(shí)例獲取InputStream和OutputStream,可以通過(guò)這兩個(gè)stream來(lái)分別讀和寫數(shù)據(jù)。

c.結(jié)束的時(shí)候調(diào)用socket實(shí)例的close()方法關(guān)閉socket連接。

?

這個(gè)流程的典型示例代碼如下:

//1.?構(gòu)造ServerSocket實(shí)例,指定服務(wù)端口。 ServerSocket?servSock?=?new?ServerSocket(servPort);while(true) {//?2.調(diào)用accept方法,建立和客戶端的連接Socket?clntSock?=?servSock.accept();SocketAddress?clientAddress?=????clntSock.getRemoteSocketAddress();System.out.println("Handling?client?at?"?+?clientAddress);//?3.?獲取連接的InputStream,OutputStream來(lái)進(jìn)行數(shù)據(jù)讀寫InputStream?in?=?clntSock.getInputStream();OutputStream?out?=?clntSock.getOutputStream();while((recvMsgSize?=?in.read(receiveBuf))?!=?-1){out.write(receiveBuf,?0,?recvMsgSize);}???//?4.操作結(jié)束,關(guān)閉socket.clntSock.close(); }

Client端

客戶端的請(qǐng)求過(guò)程稍微有點(diǎn)不一樣:

1.構(gòu)建Socket實(shí)例,通過(guò)指定的遠(yuǎn)程服務(wù)器地址和端口來(lái)建立連接。

2.通過(guò)Socket實(shí)例包含的InputStream和OutputStream來(lái)進(jìn)行數(shù)據(jù)的讀寫。

3.操作結(jié)束后調(diào)用socket實(shí)例的close方法,關(guān)閉。

示例代碼如下:

//?1.根據(jù)指定的server地址和端口,建立socket連接。 Socket?socket?=?new?Socket(server,?servPort);//?2.?根據(jù)socket實(shí)例獲取InputStream,?OutputStream進(jìn)行數(shù)據(jù)讀寫。 InputStream?in?=?socket.getInputStream(); OutputStream?out?=?socket.getOutputStream(); out.write(data);//3.操作結(jié)束,關(guān)閉socket. socket.close();

UDP

UDP和TCP有兩個(gè)典型的區(qū)別,一個(gè)就是它不需要建立連接,另外就是它在每次收發(fā)的報(bào)文都保留了消息的邊界。

server端

因?yàn)閁DP協(xié)議不需要建立連接,它的過(guò)程如下:

1. 構(gòu)造DatagramSocket實(shí)例,指定本地端口。

2. 通過(guò)DatagramSocket實(shí)例的receive方法接收DatagramPacket.DatagramPacket中間就包含了通信的內(nèi)容。

3. 通過(guò)DatagramSocket的send和receive方法來(lái)收和發(fā)DatagramPacket.

典型的交互流程代碼如下:

//?1.?構(gòu)建DatagramSocket實(shí)例,指定本地端口。 DatagramSocket?socket?=?new?DatagramSocket(servPort);//?2.?構(gòu)建需要收發(fā)的DatagramPacket報(bào)文 DatagramPacket?packet?=?new?DatagramPacket(new?byte[ECHOMAX],?ECHOMAX);while(true) {//?3.?收?qǐng)?bào)文socket.receive(packet);System.out.println("Handling?client?at?"?+?packet.getAddress().getHostAddress()+?"?on?port?"?+?packet.getPort());//?4.?發(fā)報(bào)文socket.send(packet);packet.setLength(ECHOMAX); }

client端

UDP客戶端的步驟也比較簡(jiǎn)單,主要包括下面3步:

1. 構(gòu)造DatagramSocket實(shí)例。

2.通過(guò)DatagramSocket實(shí)例的send和receive方法發(fā)送DatagramPacket報(bào)文。

3.結(jié)束后,調(diào)用DatagramSocket的close方法關(guān)閉。

因?yàn)楹蚑CP不同,UDP發(fā)送報(bào)文的時(shí)候可以在同一個(gè)本地端口隨意發(fā)送給不同的服務(wù)器,一般不需要在UDP的DatagramSocket的構(gòu)造函數(shù)中指定目的服務(wù)器的地址。

另外,UDP客戶端還有一個(gè)重要的不同就是,TCP客戶端發(fā)送echo連接消息之后會(huì)在調(diào)用read方法的時(shí)候進(jìn)入阻塞狀態(tài),而UDP這樣卻不行。因?yàn)閁DP中間是可以允許報(bào)文丟失的。如果報(bào)文丟失了,進(jìn)程一直在阻塞或者掛起的狀態(tài),則進(jìn)程會(huì)永遠(yuǎn)沒(méi)法往下走了。所以會(huì)一般設(shè)置一個(gè)setSoTimeout方法,指定在多久的時(shí)間內(nèi)沒(méi)有收到報(bào)文就放棄。也可以通過(guò)指定一個(gè)數(shù)字,循環(huán)指定的次數(shù)來(lái)讀取報(bào)文,讀到就返回,否則就放棄。

?

一個(gè)典型的UDP Client代碼示例如下:

//?1.?構(gòu)造UDP?DatagramSocket對(duì)象 DatagramSocket?socket?=?new?DatagramSocket();//?2。指定timeout時(shí)間,防止進(jìn)入無(wú)限等待狀態(tài) socket.setSoTimeout(TIMEOUT);//?3.?構(gòu)造收發(fā)的報(bào)文對(duì)象 DatagramPacket?sendPacket?=?new?DatagramPacket(bytesToSend,bytesToSend.length,?serverAddress,?servPort); DatagramPacket?receivePacket?=new?DatagramPacket(new?byte[bytesToSend.length],?bytesToSend.length);//?4.指定嘗試的次數(shù) int?tries?=?0; boolean?receivedResponse?=?false;do {socket.send(sendPacket);try{socket.receive(receivePacket);if(!receivePacket.getAddress().equals(serverAddress)){throw?new?IOException("Received?packet?from?an?unknown?source");}receivedResponse?=?true;}catch(InterruptedIOException?e){tries?+=?1;System.out.println("Timed?out,?"?+?(MAXTRIES?-?tries)?+?"");} }while((!receivedResponse)?&&?(tries?<?MAXTRIES));//?根據(jù)是否接收到報(bào)文進(jìn)行反饋 if(receivedResponse) {System.out.println("Received:?"?+?new?String(receivePacket.getData())); } else {System.out.println("No?response?--?giving?up."); }//?5.?關(guān)閉socket socket.close();

總結(jié)

TCP的server和client之間通信就好比兩個(gè)人打電話,需要互相知道對(duì)方的電話號(hào)碼,然后開(kāi)始對(duì)話。所以在兩者的連接過(guò)程中間需要指定端口和地址。

UDP的server和client之間的通信就像兩個(gè)人互相發(fā)信。我只需要知道對(duì)方的地址,然后就發(fā)信過(guò)去。對(duì)方是否收到我不知道,也不需要專門對(duì)口令似的來(lái)建立連接。

這些示例其實(shí)只是一個(gè)最簡(jiǎn)單的,單線程,也只能一次處理單個(gè)請(qǐng)求的情況。在實(shí)際應(yīng)用中一般會(huì)應(yīng)用到多線程和一些處理高并發(fā)的策略,比如基于事件驅(qū)動(dòng)的reactor模式等??梢栽诤罄m(xù)的文章中深入討論。

參考資料

1.?TCP/IP Sockets in Java

2.??TCP/IP Illustrated, Volume 1: The Protocols (2nd Edition)?

本文轉(zhuǎn)自:http://shmilyaw-hotmail-com.iteye.com/blog/1556187

感謝作者分享!

轉(zhuǎn)載于:https://blog.51cto.com/chengxuyuan/1726760

總結(jié)

以上是生活随笔為你收集整理的Java TCP/UDP socket 编程流程总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。