本學期開始學習網路編程,第一個任務是學時TCP/IP用戶端伺服器的搭建
用C寫伺服器端(Server.cpp)
#pragma comment(lib, "ws2_32.lib")//先行編譯#include <stdio.h>#include <winsock2.h>int main(int argc, char *argv[]){//step1:初始化Windows Socket 2.2庫WSADATA wsaData;WSAStartup(MAKEWORD(2,2), &wsaData);//step2:建立一個新的Socket來響應用戶端的串連請求SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//step3:填寫伺服器位址資訊int port = 5150;// 連接埠為5150SOCKADDR_IN serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(port);//serverAddr.sin_addr.s_addr =inet_addr("10.66.103.187");serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址為INADDR_ANY,使用htonl將IP地址轉換為網路格式//step4:綁定監聽連接埠bind(sListen, (SOCKADDR *)&serverAddr, sizeof(serverAddr));//step5:開始監聽,指定三向交握等待隊列長度為5listen(sListen, 5);printf("開始監聽......\n");while(true){//step6:接受新的串連SOCKETsNewConnection;SOCKADDR_IN clientAddr;memset(&clientAddr, 0, sizeof(clientAddr));int clientAddrLen = sizeof(clientAddr);sNewConnection = accept(sListen,(SOCKADDR *)&clientAddr, &clientAddrLen);//step7:新的串連建立後,就可以互相通訊了,//在這個簡單的例子中,//我們發送"Welcome to Network Programing!",然後關閉串連 //進行資料交換while(1){char message[1024];int recvSize = recv(sNewConnection,message, sizeof(message), 0);if(recvSize <= 0)break;printf("%s: %s\n", "hu", message);char data[1024] = {0};printf("%s: ","li"); scanf("%s",data);send(sNewConnection, data, strlen(message)+1, 0);}//關閉與客戶通訊的通訊端closesocket(sNewConnection);printf("%s","另一端關閉");}//step8:關閉通訊端closesocket(sListen);//step9:釋放Windows Socket DLL的相關資源WSACleanup();return 0;}
然後是用戶端(client.cpp)
#include <stdio.h>#include <winsock.h>#pragma comment(lib, "ws2_32.lib")//這句話的前面意思是靜態加入一個lib檔案也就是庫檔案ws2_32.lib檔案,提供了對以下網路相關API的支援,若使用其中的API,則應該將ws2_32.lib加入工程(否則需要動態載入ws2_32.dll)。int main(int argc, char *argv[]){//int First,Second;//step 1: 初始化Windows Socket 2.2庫 WSADATAwsaData;//功能是:存放windows socket初始化資訊WSAStartup(MAKEWORD(2,2), &wsaData);//step 2: 建立用戶端SOCKET通訊端 SOCKET sClient = socket(AF_INET, SOCK_STREAM, 0);//step 3: 設定伺服器位址 sockaddr_in serverAddr;memset(&serverAddr, 0, sizeof(sockaddr_in));//去掉沒有影響,暫時不知用途/*void *memset(void *s, int ch, size_t n);函數解釋:將s中當前位置後面的n個位元組 (typedef unsigned int size_t )用 ch 替換並返回 s 。 memset:作用是在一段記憶體塊中填充某個給定的值,它是對較大的結構體或數組進行清零操作的一種最快方法*/ serverAddr.sin_family = AF_INET; //serverAddr.sin_addr.s_addr = inet_addr(argv[1]); //serverAddr.sin_port = htons((u_short)atoi(argv[2])); serverAddr.sin_addr.s_addr =inet_addr("127.0.0.1"); //serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); serverAddr.sin_port = htons(5150);//step 4: 串連伺服器 connect(sClient, (SOCKADDR *)&serverAddr, sizeof(serverAddr));//sockaddr和sockaddr_in的區別:二者的佔用的記憶體大小是一致的,因此可以互相轉化,從這個意義上說,他們並無區別//step 5:與伺服器進行通訊while(1){char data[1024] = {0};printf("%s: ","hu");scanf("%s",data);int sendSize = send(sClient, data, strlen(data)+1, 0);//第三個參數是緩衝區中資料的長度,返回所發送的資料的總長度或SOCKET_ERROR錯誤int recvSize = recv(sClient, data, 1024, 0);//第三個參數是緩衝區的長度;成功執行時,返回接收到的位元組數。另一端已關閉則返回0。失敗返回-1printf("%s: %s\n", "li", data);}//step 6:關閉通訊端 closesocket(sClient); //step 7:釋放Winsock庫 WSACleanup();getchar();getchar(); return 0;}
最後是測試結果: