用戶端流程如下:
(1)建立通訊端(socket)
(2)向伺服器發送請求(connect)
(3)和伺服器進行通訊(send/recv)
(4)關閉通訊端
#include <Winsock2.h>#include <stdio.h>#pragma comment(lib, "WS2_32.lib") int main(){ WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(1,1); err = WSAStartup(wVersionRequested,&wsaData); if(LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return 0; } //建立通訊端 SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(6000); //向伺服器發出串連請求 connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//第一個參數是即將在其上建立串連的通訊端,第二個參數設定串連伺服器端地址資訊,第三個資訊指定伺服器端地址長度 //接收資料 char recvBuff[100]; recv(sockClient,recvBuff,100,0);//第一個參數表示已建立串連的通訊端,第二個參數指向緩衝區的指標,儲存接收的資訊,第三個參數表示緩衝區的大小,第四個參數一般設為0 printf("%s\n",recvBuff); //向伺服器發送資訊 send(sockClient,"This is lisi",strlen("This is lisi")+1,0);//第一個參數表示已建立串連的通訊端,第二個參數指向一個緩衝區,包含將要傳的資訊,第三個參數是緩衝區的長度,第四個參數一般設為0 //關閉通訊端 closesocket(sockClient); WSACleanup(); return 0;}
伺服器端流程如下:
(1)建立通訊端(socket)
(2)綁定通訊端到一個本地地址和連接埠上(bind)
(3)將通訊端設為接聽模式,準備接收客戶請求(listen)
(4)等待使用者請求,接收請求時,返回一個對應於此次串連的通訊端(accept)
(5)用返回的通訊端和用戶端進行通訊(sned/recv)
(6)返回,等待另一客戶請求
(7)關閉通訊端
#include <Winsock2.h>#include <stdio.h>#pragma comment(lib, "WS2_32.lib") int main(){ WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(1,1);//MAKEWORD宏可以獲得WSAStartup的高位和低位 err = WSAStartup(wVersionRequested,&wsaData);//WSAStartup用來載入通訊端,wVersionRequested用來指定準備載入的Winsock庫的版本,高位指副版本,地位指主要版本 if(err!=0) { return 0; } if(LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return 0; } //建立用於接聽的通訊端 SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0);//第一個參數指定地址族,對於TCP/IP協議,只能是AF_INET(PF_INET),第二個參數指定Socket類型,SOCK_STREAM產生流式通訊端,SOCK_DGRAM產生資料通訊端 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//sin_addr指定通訊端主機的IP,htonl把一個u_long類型的值從主機位元組順序轉換為TCP/IP網路位元組順序 addrSrv.sin_family = AF_INET;//sin_family表示地址族,對於IP地址,將一直是AF_INET addrSrv.sin_port = htons(6000);//sin_port指定的是將要分配給通訊端的連接埠,htons函數把一個u_short類型的值從主機位元組順序轉換為TCP/IP網路位元組順序 //綁定通訊端 bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//第一個參數指定要綁定的通訊端,第二個參數指定了通訊端的本地地址資訊,第三個參數指定第二個參數的長度 //將通訊端設為接聽模式,準備接收客戶請求 listen(sockSrv,5);//第一個參數是通訊端描述符,第二個參數是等待隊列的最大長度。 SOCKADDR_IN addrClient; int len = sizeof(SOCKADDR); while(1) { //等待客戶請求到來 SOCKET sockConn = accept(sockSrv,(SOCKADDR*)&addrClient,&len);//第一個參數是通訊端描述符,該通訊端已通過listen將其設定為接聽狀態。第二個參數是指向一個緩衝區的指標,該緩衝區用來接收串連實體的地址 //也就是當用戶端向伺服器發起串連,伺服器端接收這個串連時,儲存發起串連這個用戶端的IP地址資訊和連接埠資訊,第三個參數返回一個指向整形的指標,返回包含地址資訊的長度 char sendBuff[100]; sprintf(sendBuff,"Welcome %s to http://www.sunxin.org",inet_ntoa(addrClient.sin_addr)); printf("%s\n",sendBuff); //發送資料 send(sockConn,sendBuff,strlen(sendBuff)+1,0);//第一個參數表示已建立串連的通訊端,第二個參數指向一個緩衝區,包含將要傳的資訊,第三個參數是緩衝區的長度,第四個參數一般設為0 char recvBuff[100]; //接收資料 recv(sockConn,recvBuff,100,0);//第一個參數表示已建立串連的通訊端,第二個參數指向緩衝區的指標,儲存接收的資訊,第三個參數表示緩衝區的大小,第四個參數一般設為0 //列印接收的資料 printf("%s\n",recvBuff); //關閉通訊端 closesocket(sockConn); } return 0;}
客服端介面:
伺服器端介面: