原文地址:http://blog.csdn.net/linghu_java/article/details/43488919
因?yàn)轫?xiàng)目需要,服務(wù)端需要一個(gè)SOCKET來接收客戶端的請求,好吧,沒辦法度娘哇,結(jié)果很多都是linux的例子,功夫不負(fù)有心人啊,終于找到個(gè)demo,并且客戶端代碼詳盡,記錄之,以便以后查看。
Socket是應(yīng)用層與TCP/ip協(xié)議族通信的中間軟件抽象層,它是一組接口。在設(shè)計(jì)模式中,Socket其實(shí)就是一個(gè)門面模式,它把復(fù)雜的TCP/IP協(xié)議族隱藏在Socket接口后面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數(shù)據(jù),以符合指定的協(xié)議。

TCP/IP TCP/IP是個(gè)協(xié)議組,可分為三個(gè)層次:網(wǎng)絡(luò)層、傳輸層和應(yīng)用層。 在網(wǎng)絡(luò)層有IP協(xié)議、ICMP協(xié)議、ARP協(xié)議、RARP協(xié)議和BOOTP協(xié)議。 在傳輸層中有TCP協(xié)議與UDP協(xié)議。 在應(yīng)用層有:TCP包括FTP、HTTP、TELNET、SMTP等協(xié)議 UDP包括DNS、TFTP等協(xié)議
短連接: 連接->傳輸數(shù)據(jù)->關(guān)閉連接 HTTP是無狀態(tài)的,瀏覽器和服務(wù)器每進(jìn)行一次HTTP操作,就建立一次連接,但任務(wù)結(jié)束就中斷連接。也可以這樣說:短連接是指SOCKET連接后發(fā)送后接收完數(shù)據(jù)后馬上斷開連接。
長連接: 連接->傳輸數(shù)據(jù)->保持連接 -> 傳輸數(shù)據(jù)-> 。。。 ->關(guān)閉連接。 長連接指建立SOCKET連接后不管是否使用都保持連接,但安全性較差。
http的長連接: HTTP也可以建立長連接的,使用Connection:keep-alive,HTTP 1.1默認(rèn)進(jìn)行持久連接。HTTP1.1和HTTP1.0相比較而言,最大的區(qū)別就是增加了持久連接支持(貌似最新的 http1.0 可以顯示的指定 keep-alive),但還是無狀態(tài)的,或者說是不可以信任的。什么時(shí)候用長連接,短連接? 長連接多用于操作頻繁,點(diǎn)對點(diǎn)的通訊,而且連接數(shù)不能太多情況,。每個(gè)TCP連接都需要三步握手,這需要時(shí)間,如果每個(gè)操作都是先連接,再操作的話那么處理速度會(huì)降低很多,所以每個(gè)操作完后都不斷開,次處理時(shí)直接發(fā)送數(shù)據(jù)包就OK了,不用建立TCP連接。例如:數(shù)據(jù)庫的連接用長連接, 如果用短連接頻繁的通信會(huì)造成socket錯(cuò)誤,而且頻繁的socket 創(chuàng)建也是對資源的浪費(fèi)。而像WEB網(wǎng)站的http服務(wù)一般都用短鏈接,因?yàn)殚L連接對于服務(wù)端來說會(huì)耗費(fèi)一定的資源,而像WEB網(wǎng)站這么頻繁的成千上萬甚至上億客戶端的連接用短連接會(huì)更省一些資源,如果用長連接,而且同時(shí)有成千上萬的用戶,如果每個(gè)用戶都占用一個(gè)連接的話,那可想而知吧。所以并發(fā)量大,但每個(gè)用戶無需頻繁操作情況下需用短連好。 總之,長連接和短連接的選擇要視情況而定
發(fā)送接收方式1、異步 報(bào)文發(fā)送和接收是分開的,相互獨(dú)立的,互不影響。這種方式又分兩種情況: (1)異步雙工:接收和發(fā)送在同一個(gè)程序中,由兩個(gè)不同的子進(jìn)程分別負(fù)責(zé)發(fā)送和接收 (2)異步單工:接收和發(fā)送是用兩個(gè)不同的程序來完成。 2、同步 報(bào)文發(fā)送和接收是同步進(jìn)行,既報(bào)文發(fā)送后等待接收返回報(bào)文。 同步方式一般需要考慮超時(shí)問題,即報(bào)文發(fā)出去后不能無限等待,需要設(shè)定超時(shí)時(shí)間,超過該時(shí)間發(fā)送方不再等待讀返回報(bào)文,直接通知超時(shí)返回。 在長連接中一般是沒有條件能夠判斷讀寫什么時(shí)候結(jié)束,所以必須要加長度報(bào)文頭。讀函數(shù)先是讀取報(bào)文頭的長度,再根據(jù)這個(gè)長度去讀相應(yīng)長度的報(bào)文。

1、 首先調(diào)用Socket類的構(gòu)造函數(shù),以服務(wù)器的指定的IP地址或指定的主機(jī)名和指定的端口號(hào)為參數(shù),創(chuàng)建一個(gè)Socket流,在創(chuàng)建Socket流的過程中包含了向服務(wù)器請求建立通訊連接的過程實(shí)現(xiàn)。 2、 建立了客戶端通訊Socket后。就可以使用Socket的方法getInputStream()和getOutputStream()來創(chuàng)建輸入/輸出流。這樣,使用Socket類后,網(wǎng)絡(luò)輸入輸出也轉(zhuǎn)化為使用流對象的過程。 3、 使用輸入輸出流對象的相應(yīng)方法讀寫字節(jié)流數(shù)據(jù),因?yàn)榱鬟B接著通訊所用的Socket,Socket又是和服務(wù)器端建立連接的一個(gè)端點(diǎn),因此數(shù)據(jù)將通過連接從服務(wù)器得到或發(fā)向服務(wù)器。這時(shí)我們就可以對字節(jié)流數(shù)據(jù)按客戶端和服務(wù)器之間的協(xié)議進(jìn)行處理,完成雙方的通訊任務(wù)。 4、 待通訊任務(wù)完畢后,我們用流對象的close()方法來關(guān)閉用于網(wǎng)絡(luò)通訊的輸入輸出流,在用Socket對象的close()方法來關(guān)閉Socket。

主機(jī) A 的應(yīng)用程序要能和主機(jī) B 的應(yīng)用程序通信,必須通過 Socket 建立連接,而建立 Socket 連接必須需要底層 TCP/IP 協(xié)議來建立 TCP 連接。建立 TCP 連接需要底層 IP 協(xié)議來尋址網(wǎng)絡(luò)中的主機(jī)。我們知道網(wǎng)絡(luò)層使用的 IP 協(xié)議可以幫助我們根據(jù) IP 地址來找到目標(biāo)主機(jī),但是一臺(tái)主機(jī)上可能運(yùn)行著多個(gè)應(yīng)用程序,如何才能與指定的應(yīng)用程序通信就要通過 TCP 或 UPD 的地址也就是端口號(hào)來指定。這樣就可以通過一個(gè) Socket 實(shí)例唯一代表一個(gè)主機(jī)上的一個(gè)應(yīng)用程序的通信鏈路了。
當(dāng)客戶端要與服務(wù)端通信,客戶端首先要?jiǎng)?chuàng)建一個(gè) Socket 實(shí)例,操作系統(tǒng)將為這個(gè) Socket 實(shí)例分配一個(gè)沒有被使用的本地端口號(hào),并創(chuàng)建一個(gè)包含本地和遠(yuǎn)程地址和端口號(hào)的套接字?jǐn)?shù)據(jù)結(jié)構(gòu),這個(gè)數(shù)據(jù)結(jié)構(gòu)將一直保存在系統(tǒng)中直到這個(gè)連接關(guān)閉。在創(chuàng)建 Socket 實(shí)例的構(gòu)造函數(shù)正確返回之前,將要進(jìn)行 TCP 的三次握手協(xié)議,TCP 握手協(xié)議完成后,Socket 實(shí)例對象將創(chuàng)建完成,否則將拋出 IOException 錯(cuò)誤。 與之對應(yīng)的服務(wù)端將創(chuàng)建一個(gè) ServerSocket 實(shí)例,ServerSocket 創(chuàng)建比較簡單只要指定的端口號(hào)沒有被占用,一般實(shí)例創(chuàng)建都會(huì)成功,同時(shí)操作系統(tǒng)也會(huì)為 ServerSocket 實(shí)例創(chuàng)建一個(gè)底層數(shù)據(jù)結(jié)構(gòu),這個(gè)數(shù)據(jù)結(jié)構(gòu)中包含指定監(jiān)聽的端口號(hào)和包含監(jiān)聽地址的通配符,通常情況下都是“*”即監(jiān)聽所有地址。之后當(dāng)調(diào)用 accept() 方法時(shí),將進(jìn)入阻塞狀態(tài),等待客戶端的請求。當(dāng)一個(gè)新的請求到來時(shí),將為這個(gè)連接創(chuàng)建一個(gè)新的套接字?jǐn)?shù)據(jù)結(jié)構(gòu),該套接字?jǐn)?shù)據(jù)的信息包含的地址和端口信息正是請求源地址和端口。這個(gè)新創(chuàng)建的數(shù)據(jù)結(jié)構(gòu)將會(huì)關(guān)聯(lián)到 ServerSocket 實(shí)例的一個(gè)未完成的連接數(shù)據(jù)結(jié)構(gòu)列表中,注意這時(shí)服務(wù)端與之對應(yīng)的 Socket 實(shí)例并沒有完成創(chuàng)建,而要等到與客戶端的三次握手完成后,這個(gè)服務(wù)端的 Socket 實(shí)例才會(huì)返回,并將這個(gè) Socket 實(shí)例對應(yīng)的數(shù)據(jù)結(jié)構(gòu)從未完成列表中移到已完成列表中。所以 ServerSocket 所關(guān)聯(lián)的列表中每個(gè)數(shù)據(jù)結(jié)構(gòu),都代表與一個(gè)客戶端的建立的 TCP 連接。
備注:
Windows 下單機(jī)最大TCP連接數(shù)
調(diào)整系統(tǒng)參數(shù)來調(diào)整單機(jī)的最大TCP連接數(shù),Windows 下單機(jī)的TCP連接數(shù)有多個(gè)參數(shù)共同決定: 以下都是通過修改注冊表[HKEY_LOCAL_MACHINE /System /CurrentControlSet /Services /Tcpip /Parameters] 1. 最大TCP連接數(shù) TcpNumConnections 2. TCP關(guān)閉延遲時(shí)間 TCPTimedWaitDelay (30-240)s 3. 最大動(dòng)態(tài)端口數(shù) MaxUserPort (Default = 5000, Max = 65534) TCP客戶端和服務(wù)器連接時(shí),客戶端必須分配一個(gè)動(dòng)態(tài)端口,默認(rèn)情況下這個(gè)動(dòng)態(tài)端口的分配范圍為 1024-5000 ,也就是說默認(rèn)情況下,客戶端最多可以同時(shí)發(fā)起3977 個(gè)Socket 連接 4. 最大TCB 數(shù)量 MaxFreeTcbs系統(tǒng)為每個(gè)TCP 連接分配一個(gè)TCP 控制塊(TCP control block or TCB),這個(gè)控制塊用于緩存TCP連接的一些參數(shù),每個(gè)TCB需要分配 0.5 KB的pagepool 和 0.5KB 的Non-pagepool,也就說,每個(gè)TCP連接會(huì)占用 1KB 的系統(tǒng)內(nèi)存。非Server版本,MaxFreeTcbs 的默認(rèn)值為1000 (64M 以上物理內(nèi)存)Server 版本,這個(gè)的默認(rèn)值為 2000。也就是說,默認(rèn)情況下,Server 版本最多同時(shí)可以建立并保持2000個(gè)TCP 連接。 5. 最大TCB Hash table 數(shù)量 MaxHashTableSize TCB 是通過Hash table 來管理的。這個(gè)值指明分配 pagepool 內(nèi)存的數(shù)量,也就是說,如果MaxFreeTcbs = 1000 , 則 pagepool 的內(nèi)存數(shù)量為 500KB那么 MaxHashTableSize 應(yīng)大于 500 才行。這個(gè)數(shù)量越大,則Hash table 的冗余度就越高,每次分配和查找 TCP 連接用時(shí)就越少。這個(gè)值必須是2的冪,且最大為65536.
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注