TCP協議(三)之Windows實現
阿新 • • 發佈:2020-06-19
tcp 程式設計一般的步驟:
server(服務端)
1.new 個 socket
2.bind (IP,port)
3.listen,等待客戶端的連線
4.accept 接受客戶端的連線
5.接收(recv) 傳送資料(send)
6.關閉連線
client(客戶端)
1.new 個 socket
2.bind(ip,port)
3.connect (server.ip,server,port)
4.recv() /send()
5.關閉連線
2.程式
伺服器程式
#include <stdlib.h> #include <stdio.h> #include <WinSock2.h> #pragma comment(lib,"Ws2_32.lib ") int main() { WSADATA wsaData; struct sockaddr_in servAddr; struct sockaddr_in cliAddr; if (WSAStartup(MAKEWORD(2,2),&wsaData)) { printf("Error:RequestWindowsSocketLibrary failed!\n"); return 0; } /* 設定IP地址 */ memset(&servAddr,sizeof(servAddr)); servAddr.sin_addr.s_addr = htonl(INADDR_ANY); //繫結本機IP //servAddr.sin_addr.s_addr = inet_addr("192.168.1.53"); /* 設定埠 */ servAddr.sin_family = AF_INET; servAddr.sin_port = htons(3000); //埠為3000 /* 建立套接服務字 */ SOCKET serverSocket; serverSocket = socket(AF_INET,SOCK_STREAM,0); if (serverSocket == INVALID_SOCKET) { printf("Error:CreatServerSocket failed!\n"); return 0; } /* 繫結伺服器套接字 */ if (bind(serverSocket,(sockaddr*)&servAddr,sizeof(sockaddr)) == SOCKET_ERROR) { printf("ERROR:Bind failed!\n"); return 0; } /* 監聽埠 */ if (listen(serverSocket,20) == SOCKET_ERROR) { closesocket(serverSocket); WSACleanup(); printf("ERROR:Listen failed!\n"); return 0; } printf("linstening:%dport...\n",ntohs(servAddr.sin_port)); /* 阻塞方式等待accept */ int len = sizeof(cliAddr); SOCKET clientSocket; clientSocket = accept(serverSocket,(sockaddr*)&cliAddr,&len); printf("Connected:%s \r\n",inet_ntoa(cliAddr.sin_addr)); /* 接受訊息 */ char recvBuf[100] = { 0 }; recv(clientSocket,recvBuf,sizeof(recvBuf),0); /* 傳送訊息 */ send(clientSocket,100,NULL); closesocket(clientSocket); WSACleanup(); system("pause"); return 1; }
客戶端程式碼
#include "stdlib.h" #include <stdio.h> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") //載入 ws2_32.dll int main() { //初始化DLL //主版本號(低位元組)為2,副版本號為2,返回 0x0202 WORD sockVersion = MAKEWORD(2,2); WSADATA wsaData; //WSAStartup() 函式執行成功後,會將與 ws2_32.dll 有關的資訊寫入 WSAData 結構體變數 //(只需關注前兩個成員即可) if (WSAStartup(sockVersion,&wsaData) != 0) return 0; //建立套接字,socket() 函式用來建立套接字,確定套接字的各種屬性 //IPv4 地址、面向連線的資料傳輸方式、TCP 傳輸協議 SOCKET sock = socket(PF_INET,IPPROTO_TCP); //向伺服器發起請求,將建立的套接字與IP地址 101.76.220.219、埠 3000 繫結: sockaddr_in sockAddr; memset(&sockAddr,sizeof(sockAddr)); sockAddr.sin_family = PF_INET; //32位IP地址,s_addr 是一個整數(unsigned long),而IP地址是一個字串, //所以需要 inet_addr() 函式進行轉換 sockAddr.sin_addr.s_addr = inet_addr("101.76.218.229"); //16位的埠號,埠號需要用 htons() 函式轉換,0~1023 的埠一般由系統分配給特定的服務程式, //儘量在 1024~65536 之間分配埠號。 sockAddr.sin_port = htons(3000); //強制型別轉換,伺服器端要用 bind() 函式將套接字與特定的IP地址和埠繫結起來, //只有這樣,流經該IP地址和埠的資料才能交給套接字處理 while (connect(sock,(SOCKADDR*)& sockAddr,sizeof(SOCKADDR)) == SOCKET_ERROR) { printf("連線失敗\n"); Sleep(1000); } printf("成功連線到伺服器!\n"); char sendBuf[100] = {"Hello World"}; send(sock,sendBuf,NULL); char recvBuf[100] = { 0 }; recv(sock,0); closesocket(sock); WSACleanup(); for (int i = 0; i < 12; i++) { printf("%c",recvBuf[i]); } system("pause"); return 1; }