日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Socket通信总结(附C++实现)

發布時間:2025/7/25 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Socket通信总结(附C++实现) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Socket通信總結(附C++實現) 2012年08月16日 ? C++? 共 5870字 ? 評論數 1 ? 被圍觀 10,061+ 分享到:

文章目錄

[隱藏]
  • 一、Socket是什么
  • 二、一些基本概念
  • 三、java socket建立連接的過程 ?
  • 四、Socket 通信示例
  • 五、建立通信鏈路
  • 六、服務端代碼:
  • 七、客戶端代碼
  • 測試圖例:

? ? ? ?因為項目需要,服務端需要一個SOCKET來接收客戶端的請求,好吧,沒辦法度娘哇,結果很多都是linux的例子,功夫不負有心人啊,終于找到個demo,并且客戶端代碼詳盡,記錄之,以便以后查看。

一、Socket是什么

? ?Socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把復雜的TCP/IP協議族隱藏在Socket接口后面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數據,以符合指定的協議。

二、一些基本概念

  • TCP/IP
    ? ? ? ? ? ?TCP/IP是個協議組,可分為三個層次:網絡層、傳輸層和應用層。
    ? ? ? ? ? ?在網絡層有IP協議、ICMP協議、ARP協議、RARP協議和BOOTP協議。
    ? ? ? ? ? ?在傳輸層中有TCP協議與UDP協議。
    ? ? ? ? ? ?在應用層有:TCP包括FTP、HTTP、TELNET、SMTP等協議
    ? ? ? ? ? ?UDP包括DNS、TFTP等協議

  • 短連接:
    ? ? ? ? ? ?連接->傳輸數據->關閉連接
    ? ? ? ? ? ?HTTP是無狀態的,瀏覽器和服務器每進行一次HTTP操作,就建立一次連接,但任務結束就中斷連接。也可以這樣說:短連接是指SOCKET連接后發送后接收完數據后馬上斷開連接。

  • 長連接:
    ? ? ? ? ? ?連接->傳輸數據->保持連接 -> 傳輸數據-> 。。。 ->關閉連接。
    ? ? ? ? ? ?長連接指建立SOCKET連接后不管是否使用都保持連接,但安全性較差。

  • http的長連接:
    ? ? ? ? ? ?HTTP也可以建立長連接的,使用Connection:keep-alive,HTTP 1.1默認進行持久連接。HTTP1.1和HTTP1.0相比較而言,最大的區別就是增加了持久連接支持(貌似最新的 http1.0 可以顯示的指定 keep-alive),但還是無狀態的,或者說是不可以信任的。
    什么時候用長連接,短連接?
    ? ? ? ? ? ?長連接多用于操作頻繁,點對點的通訊,而且連接數不能太多情況,。每個TCP連接都需要三步握手,這需要時間,如果每個操作都是先連接,再操作的話那么處理速度會降低很多,所以每個操作完后都不斷開,次處理時直接發送數據包就OK了,不用建立TCP連接。例如:數據庫的連接用長連接, 如果用短連接頻繁的通信會造成socket錯誤,而且頻繁的socket 創建也是對資源的浪費。
    而像WEB網站的http服務一般都用短鏈接,因為長連接對于服務端來說會耗費一定的資源,而像WEB網站這么頻繁的成千上萬甚至上億客戶端的連接用短連接會更省一些資源,如果用長連接,而且同時有成千上萬的用戶,如果每個用戶都占用一個連接的話,那可想而知吧。所以并發量大,但每個用戶無需頻繁操作情況下需用短連好。
    ? ? ? ? ? ?總之,長連接和短連接的選擇要視情況而定

  • 發送接收方式
    1、異步
    ? ? ? ?報文發送和接收是分開的,相互獨立的,互不影響。這種方式又分兩種情況:
    ? ? ? ?(1)異步雙工:接收和發送在同一個程序中,由兩個不同的子進程分別負責發送和接收
    ? ? ? ?(2)異步單工:接收和發送是用兩個不同的程序來完成。
    2、同步
    ? ? ? ?報文發送和接收是同步進行,既報文發送后等待接收返回報文。 同步方式一般需要考慮超時問題,即報文發出去后不能無限等待,需要設定超時時間,超過該時間發送方不再等待讀返回報文,直接通知超時返回。
    ? ? ? ?在長連接中一般是沒有條件能夠判斷讀寫什么時候結束,所以必須要加長度報文頭。讀函數先是讀取報文頭的長度,再根據這個長度去讀相應長度的報文。 ?

  • 三、java socket建立連接的過程 ?

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

    四、Socket 通信示例

    ? ? ? ?主機 A 的應用程序要能和主機 B 的應用程序通信,必須通過 Socket 建立連接,而建立 Socket 連接必須需要底層 TCP/IP 協議來建立 TCP 連接。建立 TCP 連接需要底層 IP 協議來尋址網絡中的主機。我們知道網絡層使用的 IP 協議可以幫助我們根據 IP 地址來找到目標主機,但是一臺主機上可能運行著多個應用程序,如何才能與指定的應用程序通信就要通過 TCP 或 UPD 的地址也就是端口號來指定。這樣就可以通過一個 Socket 實例唯一代表一個主機上的一個應用程序的通信鏈路了。

    五、建立通信鏈路

    ? ? ? ?當客戶端要與服務端通信,客戶端首先要創建一個 Socket 實例,操作系統將為這個 Socket 實例分配一個沒有被使用的本地端口號,并創建一個包含本地和遠程地址和端口號的套接字數據結構,這個數據結構將一直保存在系統中直到這個連接關閉。在創建 Socket 實例的構造函數正確返回之前,將要進行 TCP 的三次握手協議,TCP 握手協議完成后,Socket 實例對象將創建完成,否則將拋出 IOException 錯誤。
    ? ? ? ?與之對應的服務端將創建一個 ServerSocket 實例,ServerSocket 創建比較簡單只要指定的端口號沒有被占用,一般實例創建都會成功,同時操作系統也會為 ServerSocket 實例創建一個底層數據結構,這個數據結構中包含指定監聽的端口號和包含監聽地址的通配符,通常情況下都是“*”即監聽所有地址。之后當調用 accept() 方法時,將進入阻塞狀態,等待客戶端的請求。當一個新的請求到來時,將為這個連接創建一個新的套接字數據結構,該套接字數據的信息包含的地址和端口信息正是請求源地址和端口。這個新創建的數據結構將會關聯到 ServerSocket 實例的一個未完成的連接數據結構列表中,注意這時服務端與之對應的 Socket 實例并沒有完成創建,而要等到與客戶端的三次握手完成后,這個服務端的 Socket 實例才會返回,并將這個 Socket 實例對應的數據結構從未完成列表中移到已完成列表中。所以 ServerSocket 所關聯的列表中每個數據結構,都代表與一個客戶端的建立的 TCP 連接。

    ? ? ? ?備注:

    ? ? ? ? Windows 下單機最大TCP連接數

    ? ? ? ? ? ?調整系統參數來調整單機的最大TCP連接數,Windows 下單機的TCP連接數有多個參數共同決定:
    ? ? ? ? ? ?以下都是通過修改注冊表[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
    ? ? ? ? ? ?1. ? ?最大TCP連接數 ? ? ? ?TcpNumConnections
    ? ? ? ? ? ?2. ? ?TCP關閉延遲時間 ? ?TCPTimedWaitDelay ? ?(30-240)s ? ? ? ?
    ? ? ? ? ? ?3. ? ?最大動態端口數 ? MaxUserPort ?(Default = 5000, Max = 65534) TCP客戶端和服務器連接時,客戶端必須分配一個動態端口,默認情況下這個動態端口的分配范圍為 1024-5000 ,也就是說默認情況下,客戶端最多可以同時發起3977 個Socket 連接 ? ?
    ? ? ? ? ? ?4. ? 最大TCB 數量 ? MaxFreeTcbs系統為每個TCP 連接分配一個TCP 控制塊(TCP control block or TCB),這個控制塊用于緩存TCP連接的一些參數,每個TCB需要分配 0.5 KB的pagepool 和 0.5KB 的Non-pagepool,也就說,每個TCP連接會占用 1KB 的系統內存。非Server版本,MaxFreeTcbs 的默認值為1000 (64M 以上物理內存)Server 版本,這個的默認值為 2000。也就是說,默認情況下,Server 版本最多同時可以建立并保持2000個TCP 連接。
    ? ? ? ? ? ?5. ? 最大TCB Hash table 數量 ? MaxHashTableSize TCB 是通過Hash table 來管理的。這個值指明分配 pagepool 內存的數量,也就是說,如果MaxFreeTcbs = 1000 , 則 pagepool 的內存數量為 500KB那么 MaxHashTableSize 應大于 500 才行。這個數量越大,則Hash table 的冗余度就越高,每次分配和查找 TCP ?連接用時就越少。這個值必須是2的冪,且最大為65536.

    六、服務端代碼:

    [cpp] view plaincopy
  • /*?????
  • ?*?testSocketService.c?????
  • ?*?????
  • ?*??Created?on:?2012-8-16?????
  • ?*??????Author:?皓月繁星?????
  • ?*/??
  • #include?<WINSOCK2.H>???
  • #include?<stdio.h>?????
  • ????????????????????
  • #define?PORT???????????5150????
  • #define?MSGSIZE????????1024????
  • ???????????????????
  • #pragma?comment(lib,?"ws2_32.lib")??????
  • ???????????????????
  • int?main()??????
  • {??????
  • ????WSADATA?wsaData;??????
  • ????SOCKET?sListen;??????
  • ????SOCKET?sClient;??????
  • ????SOCKADDR_IN?local;??????
  • ????SOCKADDR_IN?client;??????
  • ????char?szMessage[MSGSIZE];??????
  • ????int?ret;??????
  • ????int?iaddrSize?=?sizeof(SOCKADDR_IN);??????
  • ????WSAStartup(0x0202,?&wsaData);??????
  • ???????????????????
  • ????sListen?=?socket(AF_INET,?SOCK_STREAM,?IPPROTO_TCP);??????
  • ???????????????????
  • ????local.sin_family?=?AF_INET;??????
  • ????local.sin_port?=?htons(PORT);??????
  • ????local.sin_addr.s_addr?=?htonl(INADDR_ANY);??????
  • ????bind(sListen,?(struct?sockaddr?*)?&local,?sizeof(SOCKADDR_IN));??????
  • ???????????????????
  • ????listen(sListen,?1);??????
  • ???????????????????
  • ????sClient?=?accept(sListen,?(struct?sockaddr?*)?&client,?&iaddrSize);??????
  • ????printf("Accepted?client:%s:%d\n",?inet_ntoa(client.sin_addr),??????
  • ????????????ntohs(client.sin_port));??????
  • ???????????????????
  • ????while?(TRUE)?{??????
  • ????????ret?=?recv(sClient,?szMessage,?MSGSIZE,?0);??????
  • ????????szMessage[ret]?=?'\0';??????
  • ????????printf("Received?[%d?bytes]:?'%s'\n",?ret,?szMessage);??????
  • ????}??????
  • ????return?0;??????
  • ??}??
  • 七、客戶端代碼

    [cpp] view plaincopy
  • /*?????
  • ?*?testSocketClient.c?????
  • ?*?????
  • ?*??Created?on:?2012-8-16?????
  • ?*??????Author:?皓月繁星?????
  • ?*/??
  • #include?<WINSOCK2.H>???
  • #include?<stdio.h>?????
  • ????????????????????
  • //定義程序中使用的常量??????
  • #define?SERVER_ADDRESS?"127.0.0.1"?//服務器端IP地址??????
  • #define?PORT???????????5150?????????//服務器的端口號??????
  • #define?MSGSIZE????????1024?????????//收發緩沖區的大小??????
  • #pragma?comment(lib,?"ws2_32.lib")??????
  • ???????????????????
  • int?main()??????
  • {??????
  • ????WSADATA?wsaData;??????
  • ????//連接所用套節字??????
  • ????SOCKET?sClient;??????
  • ????//保存遠程服務器的地址信息??????
  • ????SOCKADDR_IN?server;??????
  • ????//收發緩沖區??????
  • ????char?szMessage[MSGSIZE];??????
  • ????//成功接收字節的個數??????
  • ????int?ret;??????
  • ???????????????????
  • ????//?Initialize?Windows?socket?library??????
  • ????WSAStartup(0x0202,?&wsaData);??????
  • ???????????????????
  • ????//?創建客戶端套節字??????
  • ????sClient?=?socket(AF_INET,?SOCK_STREAM,?IPPROTO_TCP);?//AF_INET指明使用TCP/IP協議族;??????
  • ?????????????????????????????????????????????????????????//SOCK_STREAM,?IPPROTO_TCP具體指明使用TCP協議??????
  • ????//?指明遠程服務器的地址信息(端口號、IP地址等)??????
  • ????memset(&server,?0,?sizeof(SOCKADDR_IN));?//先將保存地址的server置為全0??????
  • ????server.sin_family?=?PF_INET;?//聲明地址格式是TCP/IP地址格式??????
  • ????server.sin_port?=?htons(PORT);?//指明連接服務器的端口號,htons()用于?converts?values?between?the?host?and?network?byte?order??????
  • ????server.sin_addr.s_addr?=?inet_addr(SERVER_ADDRESS);?//指明連接服務器的IP地址??????
  • ????????????????????????????????????????????????????????//結構SOCKADDR_IN的sin_addr字段用于保存IP地址,sin_addr字段也是一個結構體,sin_addr.s_addr用于最終保存IP地址??????
  • ????????????????????????????????????????????????????????//inet_addr()用于將?形如的"127.0.0.1"字符串轉換為IP地址格式??????
  • ????//連到剛才指明的服務器上??????
  • ????connect(sClient,?(struct?sockaddr?*)?&server,?sizeof(SOCKADDR_IN));?//連接后可以用sClient來使用這個連接??????
  • ????????????????????????????????????????????????????????????????????????//server保存了遠程服務器的地址信息??????
  • ????while?(TRUE)?{??????
  • ????????printf("Send:");??????
  • ????????//從鍵盤輸入??????
  • ????????gets(szMessage);?//The?gets()?functionreads?characters?from?stdin?and?loads?them?into?szMessage??????
  • ????????//?發送數據??????
  • ????????send(sClient,?szMessage,?strlen(szMessage),?0);?//sClient指明用哪個連接發送;?szMessage指明待發送數據的保存地址?;strlen(szMessage)指明數據長度??????
  • ????}??????
  • ???????????????????
  • ????//?釋放連接和進行結束工作??????
  • ????closesocket(sClient);??????
  • ????WSACleanup();??????
  • ????return?0;??????
  • }??
  • 測試圖例:

    ?

    總結

    以上是生活随笔為你收集整理的Socket通信总结(附C++实现)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。