C++ Socket编程实例解析
Socket
socket本質是編程接口(API),對TCP/IP的封裝,TCP/IP也要提供可供程序員做網絡開發所用的接口,這就是Socket編程接口;HTTP是轎車,提供了封裝或者顯示數據的具體形式;Socket是發動機,提供了網絡通信的能力。
在Internet上的主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,并綁定到一個端口上,不同的端口對應于不同的服務。Socket正如其英文原意那樣,像一個多孔插座。一臺主機猶如布滿各種插座的房間,每個插座有一個編號,有的插座提供220伏交流電, 有的提供110伏交流電,有的則提供有線電視節目。 客戶軟件將插頭插到不同編號的插座,就可以得到不同的服務。—— [ 維基百科]
有三種不同形式的套接字:
- 流式套接字(SOCK_STREAM)
- 流套接字用于提供面向連接、可靠的數據傳輸服務。該服務將保證數據能夠實現無差錯、無重復發送,并按順序接收。流套接字之所以能夠實現可靠的數據服務,原因在于其使用了傳輸控制協議,即TCP(The Transmission Control Protocol)協議。
- 數據包套接字(SOCK_DGRAM)
- 數據包套接字提供了一種無連接的服務。該服務并不能保證數據傳輸的可靠性,數據有可能在傳輸過程中丟失或出現數據重復,且無法保證順序地接收到數據。數據包套接字使用UDP(User Datagram Protocol)協議進行數據的傳輸。由于數據包套接字不能保證數據傳輸的可靠性,對于有可能出現的數據丟失情況,需要在程序中做相應的處理。
- 原始套接字(SOCK_RAW)
原始套接字(SOCKET_RAW)允許對較低層次的協議直接訪問,比如IP、 ICMP協議,它常用于檢驗新的協議實現,或者訪問現有服務中配置的新設備,因為RAW SOCKET可以自如地控制Windows下的多種協議,能夠對網絡底層的傳輸機制進行控制,所以可以應用原始套接字來操縱網絡層和傳輸層應用。比如,我們可以通過RAW SOCKET來接收發向本機的ICMP、IGMP協議包,或者接收TCP/IP棧不能夠處理的IP包,也可以用來發送一些自定包頭或自定協議的IP包。網絡監聽技術很大程度上依賴于SOCKET_RAW
基于TCP的Socket使用流式套接字,相比于使用數據包套接字的UDP來講,TCP可以使程序員不必關心數據正確性及順序正確性,缺點是效率較低。
基于TCP的Socket編程最常見的應用場景是在C/S架構下的分布式應用,針對客戶端和服務器端提供不同的Socket系統調用。
下面舉例說明其使用方式:
Server端
#include <Winsock2.h> #include <cstdio> #pragma comment(lib,"ws2_32.lib") void main() {WSADATA wsaData;SOCKET sockServer;SOCKADDR_IN addrServer;SOCKET sockClient;SOCKADDR_IN addrClient;WSAStartup(MAKEWORD(2,2),&wsaData);sockServer=socket(AF_INET,SOCK_STREAM,0);addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//INADDR_ANY表示任何IPaddrServer.sin_family=AF_INET;addrServer.sin_port=htons(6000);//綁定端口6000bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));//Listen監聽端listen(sockServer,5);//5為等待連接數目printf("服務器已啟動:\n監聽中...\n");int len=sizeof(SOCKADDR);charsendBuf[100];//發送至客戶端的字符串charrecvBuf[100];//接受客戶端返回的字符串//會阻塞進程,直到有客戶端連接上來為止sockClient=accept(sockServer,(SOCKADDR*)&addrClient,&len);//接收并打印客戶端數據recv(sockClient,recvBuf,100,0);printf("%s\n",recvBuf);//關閉socketclosesocket(sockClient);WSACleanup(); }Client端
#include <Winsock2.h> #include <cstdio> #pragma comment(lib,"ws2_32.lib") void main() {WSADATA wsaData;SOCKET sockClient;//客戶端SocketSOCKADDR_IN addrServer;//服務端地址WSAStartup(MAKEWORD(2,2),&wsaData);//新建客戶端socketsockClient=socket(AF_INET,SOCK_STREAM,0);//定義要連接的服務端地址addrServer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//目標IP(127.0.0.1是回送地址)addrServer.sin_family=AF_INET;addrServer.sin_port=htons(6000);//連接端口6000//連接到服務端connect(sockClient,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));//發送數據char message[20]="HelloSocket!";send(sockClient,message,strlen(message)+1,0);//關閉socketclosesocket(sockClient);WSACleanup(); }附Socket編程步驟:
服務器端編程的步驟:
1:加載套接字庫,創建套接字(WSAStartup()/socket());
2:綁定套接字到一個IP地址和一個端口上(bind());
3:將套接字設置為監聽模式等待連接請求(listen());
4:請求到來后,接受連接請求,返回一個新的對應于此次連接的套接字(accept());
5:用返回的套接字和客戶端進行通信(send()/recv());
6:返回,等待另一連接請求;
7:關閉套接字,關閉加載的套接字庫(closesocket()/WSACleanup())。
客戶端編程的步驟:
1:加載套接字庫,創建套接字(WSAStartup()/socket());
2:向服務器發出連接請求(connect());
3:和服務器端進行通信(send()/recv());
4:關閉套接字,關閉加載的套接字庫(closesocket()/WSACleanup())。
CSDN博客
總結
以上是生活随笔為你收集整理的C++ Socket编程实例解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实践Hive的点点滴滴
- 下一篇: c++开源库rapidxml介绍与示例