實現簡單的Socket通信案例(個人嘗試)
服務端代碼(Server)

#include <stdio.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") #define PORT 9999 int main() { WSADATA WSAData; SOCKET sock, msgsock; struct sockaddr_in ServerAddr; if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR) { ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(PORT); ServerAddr.sin_addr.s_addr = INADDR_ANY; sock = socket(AF_INET, SOCK_STREAM, 0); int BindRet = bind(sock, (LPSOCKADDR)&ServerAddr, sizeof(ServerAddr)); int LinsRet = listen(sock, 10); printf("------------------------------------------------------------------------------------------\n"); printf("綁定狀態: %d\t 偵聽狀態: %d\t 綁定端口: %d\n", BindRet, LinsRet, ntohs(ServerAddr.sin_port)); printf("------------------------------------------------------------------------------------------\n"); } while (1) { char buf[1024]; msgsock = accept(sock, (LPSOCKADDR)0, (int *)0); memset(buf, 0, sizeof(buf)); recv(msgsock, buf, 1024, 0); printf("客戶IP: %s\t 端口:%d\t 數據:%s\n", inet_ntoa(ServerAddr.sin_addr), htons(ServerAddr.sin_port),buf); if (!strcmp(buf, "Success")) { printf("客戶端已就緒...\n"); } closesocket(msgsock); } closesocket(sock); WSACleanup(); return 0; }
客戶端代碼(Client)

#include <winsock2.h> #include <stdio.h> #pragma comment(lib,"ws2_32.lib") #define IP "127.0.0.1" #define PORT 9999 //#ifdef _MSC_VER //#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) //#endif int main() { while (1) { WSADATA WSAData; SOCKET sock; struct sockaddr_in ClientAddr; if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR) { ClientAddr.sin_family = AF_INET; //指Internet域 ClientAddr.sin_port = htons(PORT); //指定服務端所預留的端口 ClientAddr.sin_addr.s_addr = inet_addr(IP); //指定服務端所綁定的IP地址 sock = socket(AF_INET, SOCK_STREAM, 0); int Ret = connect(sock, (LPSOCKADDR)&ClientAddr, sizeof(ClientAddr)); if (Ret == 0) { char Status[] = "Success"; int ServerRet = send(sock, Status, sizeof(Status), 0); if (ServerRet != 0) { printf("發送給服務器Success狀態成功..\n"); } } } closesocket(sock); WSACleanup(); Sleep(5000); } return 0; }
實現Socket單工通信案例
服務端代碼(Server)

#include <stdio.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") //把ws2_32.lib加到Link頁的連接庫 #define PORT 15001 //通信的端口(指服務器端) #define ERROR 0 #define BUFFER_SIZE 1024 //注意:此Server端數據接收緩沖區 >= Client端數據發送緩沖區 ,否則造成緩沖區溢出 /* 服務端原理: 1、服務器進程創建套接字 2、將本地地址綁定到所創建的套接字上,以三元組{<通信協議>,<IP地址>,<端口號>}在網絡上標識該套接字 3、將套接字置入監聽模式,並准備接受連接請求 */ int main() { WSADATA WSAData; if(WSAStartup(MAKEWORD(2,0),&WSAData)==SOCKET_ERROR) //啟動winsock ,WSAStartup()函數對Winsock DLL進行初始化 { printf("Socket initialize fail!\n"); exit(1); } SOCKET sock; //服務進程創建套接字句柄(用於監聽) if((sock=socket(AF_INET,SOCK_STREAM,0))==ERROR) //調用socket()函數創建一個流套接字,參數(網絡地址類型,套接字類型,網絡協議) { printf("Socket create!\n"); WSACleanup(); exit(1); } struct sockaddr_in ServerAddr; //sockaddr_in結構用來標識TCP/IP協議下的地址,可強制轉換為sockaddr結構 ServerAddr.sin_family=AF_INET; //sin_family字段必須設為AF_INET,表示該Socket處於Internet域 ServerAddr.sin_port=htons(PORT); //sin_port字段用於指定服務端口,注意避免沖突 ServerAddr.sin_addr.s_addr=INADDR_ANY; //sin_addr字段用於把一個IP地址保存為一個4字節的數,無符號長整型,根據不同用法還可表示本地或遠程IP地址 if(bind(sock,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr))==SOCKET_ERROR) //調用bind()函數將本地地址綁定到所創建的套接字上,以在網絡上標識該套接字 { printf("Bind fail!\n"); closesocket(sock); WSACleanup(); exit(1); } printf("Server Socket Port:%d\n",ntohs(ServerAddr.sin_port)); if(listen(sock,10)==SOCKET_ERROR) //調用listen()函數將套接字置入監聽模式並准備接受連接請求,參數(已捆綁未連接的套接字描述字,正在等待連接的最大隊列長度) { printf("Listen fail!\n"); closesocket(sock); WSACleanup(); exit(1); } SOCKET msgsock; //創建一個新的套接字(用於接收accept函數的返回值,即表示已經接受的那個客戶端的連接,進而接收Client發來的數據) char buf[BUFFER_SIZE]; //數據接收緩沖區 while(1) { if((msgsock=accept(sock,(LPSOCKADDR)0,(int *)0))==INVALID_SOCKET) //進入監聽狀態后,調用accept()函數接收客戶端的連接請求,並把連接傳給msgsock套接字,原sock套接字繼續監聽其他客戶機連接請求 { printf("Accept fail!\n"); continue; } memset(buf,0,sizeof(buf)); //初始化數據接收緩沖區 recv(msgsock,buf,BUFFER_SIZE,0); //接收客戶端發送過來的數據 if(buf[0]=='e' && buf[1]=='x' && buf[2]=='i' && buf[3]=='t') //"exit"命令,退出程序 { printf("The End.\n"); break; } printf("C:\\Socket\\Server>%s",buf); closesocket(msgsock); } closesocket(sock); //關閉套接字 WSACleanup(); //終止對Winsock DLL的使用,並釋放資源 return 0; }
客戶端代碼(Client)

#include <winsock2.h> #include <stdio.h> #pragma comment(lib,"ws2_32.lib") //把ws2_32.lib加到Link頁的連接庫 //#define IP "172.18.68.243" //在兩台計算機上測試,IP為Server端的IP地址 #define IP "127.0.0.1" //在一台計算機上測試,IP為本地回送地址 #define PORT 15001 //注意:客戶端設置通信的端口 = 服務端的端口 #define BUFFER_SIZE 1024 //數據發送緩沖區大小 int main() { char buf[BUFFER_SIZE]; //buf數組存放客戶端發送的消息 int inputLen; //用於輸入字符自增變量 while(1) { printf("C:\\Socket\\Client>"); inputLen=0; memset(buf,0,sizeof(buf)); while((buf[inputLen++]=getchar())!='\n') //輸入以回車鍵為結束標識 { ; } if(buf[0]=='e' && buf[1]=='x' && buf[2]=='i' && buf[3]=='t') { printf("The End.\n"); break; } WSADATA WSAData; if(WSAStartup(MAKEWORD(2,0),&WSAData)==SOCKET_ERROR) //WSAStartup()函數對Winsock DLL進行初始化 { printf("Socket initialize fail!\n"); continue; } SOCKET sock; //客戶端進程創建套接字 if((sock=socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR) //創建流套接字(與服務端保持一致) { printf("Socket create fail!\n"); WSACleanup(); continue; } struct sockaddr_in ClientAddr; //sockaddr_in結構用來標識TCP/IP協議下的地址,可強制轉換為sockaddr結構 ClientAddr.sin_family=AF_INET; //指Internet域 ClientAddr.sin_port=htons(PORT); //指定服務端所預留的端口 ClientAddr.sin_addr.s_addr=inet_addr(IP); //指定服務端所綁定的IP地址 if(connect(sock,(LPSOCKADDR)&ClientAddr,sizeof(ClientAddr))==SOCKET_ERROR) //調用connect()函數,向服務器進程發出連接請求 { printf("Connect fail!\n"); closesocket(sock); WSACleanup(); continue; } send(sock,buf,BUFFER_SIZE,0); //向服務器發送數據 closesocket(sock); //關閉套接字 WSACleanup(); //終止對Winsock DLL的使用,並釋放資源,以備下一次使用 } return 0; }
轉載:https://blog.csdn.net/lynch0571
實現Socket雙工通信案例
服務端代碼(Server)

#include <stdio.h> #include <Winsock2.h> //Socket的函數調用 #include <windows.h> #define BUF_SIZE 6400 // 緩沖區大小 #pragma comment (lib, "ws2_32") // 使用WINSOCK2.H時,則需要庫文件WS2_32.LIB DWORD WINAPI Rcv(LPVOID lpParam) { SOCKET sClient = *(SOCKET*)lpParam; int retVal; char bufRecv[BUF_SIZE]; memset(bufRecv, 0, sizeof(bufRecv)); while (1) { retVal = recv(sClient, bufRecv, BUF_SIZE, 0); if (retVal == SOCKET_ERROR) { printf("recive faild!\n"); break; } else { printf("收到客戶端消息:%s\n", bufRecv); } } return 0; } DWORD WINAPI Snd(LPVOID lpParam) { SOCKET sClient = *(SOCKET*)lpParam; int retVal; char bufSend[BUF_SIZE]; memset(bufSend, 0, sizeof(bufSend)); while (1) { gets(bufSend); retVal = send(sClient, bufSend, strlen(bufSend) + sizeof(char), 0); if (retVal == SOCKET_ERROR) { printf("send faild!\n"); break; } } return 0; } int main(int argc, char* argv[]) { // 初始化套接字動態庫 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { printf("winsock load faild!\n"); return 1; } // 創建服務段套接字 SOCKET sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sServer == INVALID_SOCKET) { printf("socket faild!\n"); WSACleanup(); return -1; } // 服務端地址 sockaddr_in addrServ; addrServ.sin_family = AF_INET; addrServ.sin_port = htons(9999); addrServ.sin_addr.s_addr = htonl(INADDR_ANY); // 綁定套接字 if (bind(sServer, (const struct sockaddr*)&addrServ, sizeof(addrServ)) == SOCKET_ERROR) { printf("bind faild!\n"); closesocket(sServer); WSACleanup(); return -1; } printf("Server is On IP:[%s],port:[%d]\n", inet_ntoa(addrServ.sin_addr), ntohs(addrServ.sin_port)); // 監聽套接字 數字表示最多能監聽客戶個數 if (listen(sServer, 5) == SOCKET_ERROR) { printf("listen faild!\n"); closesocket(sServer); WSACleanup(); return -1; } SOCKET sClient; // 客戶端套接字 sockaddr_in addrClient; int addrClientLen = sizeof(addrClient); sClient = accept(sServer, (sockaddr FAR*)&addrClient, &addrClientLen); if (sClient == INVALID_SOCKET) { printf("accept faild!\n"); closesocket(sServer); WSACleanup(); return -1; } printf("accepted client IP:[%s],port:[%d]\n", inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port)); HANDLE hThread1, hThread2; DWORD dwThreadId1, dwThreadId2; hThread1 = ::CreateThread(NULL, NULL, Snd, (LPVOID*)&sClient, 0, &dwThreadId1); hThread2 = ::CreateThread(NULL, NULL, Rcv, (LPVOID*)&sClient, 0, &dwThreadId2); ::WaitForSingleObject(hThread1, INFINITE); ::WaitForSingleObject(hThread2, INFINITE); ::CloseHandle(hThread1); ::CloseHandle(hThread2); closesocket(sClient); WSACleanup(); // 資源釋放 return 0; }
客戶端代碼(Client)

#include <stdio.h> #include <Winsock2.h> //Socket的函數調用 #include <windows.h> #define BUF_SIZE 6400 #pragma comment (lib, "ws2_32") // 使用WINSOCK2.H時,則需要庫文件WS2_32.LIB DWORD WINAPI Rcv(LPVOID lpParam) { SOCKET sHost = *(SOCKET*)lpParam; int retVal; char bufRecv[BUF_SIZE]; memset(bufRecv, 0, sizeof(bufRecv)); while (1) { retVal = recv(sHost, bufRecv, BUF_SIZE, 0); if (retVal == SOCKET_ERROR) { printf("recive faild!\n"); break; } else { printf("收到服務器消息:%s\n", bufRecv); } } return 0; } DWORD WINAPI Snd(LPVOID lpParam) { SOCKET sHost = *(SOCKET*)lpParam; int retVal; char bufSend[BUF_SIZE]; memset(bufSend, 0, sizeof(bufSend)); while (1) { gets(bufSend); retVal = send(sHost, bufSend, strlen(bufSend) + sizeof(char), 0); if (retVal == SOCKET_ERROR) { printf("send faild!\n"); break; } } return 0; } int main(int argc, char* argv[]) { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { printf("Winsock load faild!\n"); return 1; } // 服務器套接字 SOCKET sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sHost == INVALID_SOCKET) { printf("socket faild!\n"); WSACleanup(); return -1; } SOCKADDR_IN servAddr; servAddr.sin_family = AF_INET; // 注意 當把客戶端程序發到別人的電腦時 此處IP需改為服務器所在電腦的IP servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); servAddr.sin_port = htons(9999); // 連接服務器 if (connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) { printf("connect faild!\n"); closesocket(sHost); WSACleanup(); return -1; } printf("連接到服務器 IP:[%s],port:[%d]\n", inet_ntoa(servAddr.sin_addr), ntohs(servAddr.sin_port)); HANDLE hThread1, hThread2; DWORD dwThreadId1, dwThreadId2; hThread1 = ::CreateThread(NULL, NULL, Snd, (LPVOID)&sHost, 0, &dwThreadId1); hThread2 = ::CreateThread(NULL, NULL, Rcv, (LPVOID)&sHost, 0, &dwThreadId2); ::WaitForSingleObject(hThread1, INFINITE); ::WaitForSingleObject(hThread2, INFINITE); ::CloseHandle(hThread1); ::CloseHandle(hThread2); closesocket(sHost); WSACleanup(); return 0; }
轉載:https://www.cnblogs.com/wuyepeng/
實現文件傳輸

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <WinSock2.h> #define PORT 8087 #define SERVER_IP "127.0.0.1" #define BUFFER_SIZE 1024 #define FILE_NAME_MAX_SIZE 512 #pragma comment(lib, "WS2_32") int main() { // 聲明並初始化一個服務端(本地)的地址結構 sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.S_un.S_addr = INADDR_ANY; server_addr.sin_port = htons(PORT); // 初始化socket dll WSADATA wsaData; WORD socketVersion = MAKEWORD(2, 0); if (WSAStartup(socketVersion, &wsaData) != 0) { printf("Init socket dll error!"); exit(1); } // 創建socket SOCKET m_Socket = socket(AF_INET, SOCK_STREAM, 0); if (SOCKET_ERROR == m_Socket) { printf("Create Socket Error!"); exit(1); } //綁定socket和服務端(本地)地址 if (SOCKET_ERROR == bind(m_Socket, (LPSOCKADDR)&server_addr, sizeof(server_addr))) { printf("Server Bind Failed: %d", WSAGetLastError()); exit(1); } //監聽 if (SOCKET_ERROR == listen(m_Socket, 10)) { printf("Server Listen Failed: %d", WSAGetLastError()); exit(1); } while (1) { printf("Listening To Client...\n"); sockaddr_in client_addr; int client_addr_len = sizeof(client_addr); SOCKET m_New_Socket = accept(m_Socket, (sockaddr *)&client_addr, &client_addr_len); if (SOCKET_ERROR == m_New_Socket) { printf("Server Accept Failed: %d", WSAGetLastError()); break; } char buffer[BUFFER_SIZE]; memset(buffer, 0, BUFFER_SIZE); if (recv(m_New_Socket, buffer, BUFFER_SIZE, 0) < 0) { printf("Server Receive Data Failed!"); break; } char file_name[FILE_NAME_MAX_SIZE + 1]; memset(file_name, 0, FILE_NAME_MAX_SIZE + 1); strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer)); printf("%s\n", file_name); FILE * fp = fopen(file_name, "rb"); //windows下是"rb",表示打開一個只讀的二進制文件 if (NULL == fp) { printf("File: %s Not Found\n", file_name); } else { memset(buffer, 0, BUFFER_SIZE); int length = 0; while ((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0) { if (send(m_New_Socket, buffer, length, 0) < 0) { printf("Send File: %s Failed\n", file_name); break; } memset(buffer, 0, BUFFER_SIZE); } fclose(fp); printf("File: %s Transfer Successful!\n", file_name); } closesocket(m_New_Socket); } closesocket(m_Socket); //釋放winsock庫 WSACleanup(); return 0; }

/************************************************************************* > File Name: Win_Client.c > Author: SongLee ************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <WinSock2.h> #define PORT 8087 #define SERVER_IP "127.0.0.1" #define BUFFER_SIZE 1024 #define FILE_NAME_MAX_SIZE 512 #pragma comment(lib, "WS2_32") int main() { // 初始化socket dll WSADATA wsaData; WORD socketVersion = MAKEWORD(2, 0); if (WSAStartup(socketVersion, &wsaData) != 0) { printf("Init socket dll error!"); exit(1); } //創建socket SOCKET c_Socket = socket(AF_INET, SOCK_STREAM, 0); if (SOCKET_ERROR == c_Socket) { printf("Create Socket Error!"); system("pause"); exit(1); } //指定服務端的地址 sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.S_un.S_addr = inet_addr(SERVER_IP); server_addr.sin_port = htons(PORT); if (SOCKET_ERROR == connect(c_Socket, (LPSOCKADDR)&server_addr, sizeof(server_addr))) { printf("Can Not Connect To Server IP!\n"); system("pause"); exit(1); } //輸入文件名 char file_name[FILE_NAME_MAX_SIZE + 1]; memset(file_name, 0, FILE_NAME_MAX_SIZE + 1); printf("Please Input File Name On Server: "); scanf("%s", &file_name); char buffer[BUFFER_SIZE]; memset(buffer, 0, BUFFER_SIZE); strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE ? BUFFER_SIZE : strlen(file_name)); //向服務器發送文件名 if (send(c_Socket, buffer, BUFFER_SIZE, 0) < 0) { printf("Send File Name Failed\n"); system("pause"); exit(1); } //打開文件,准備寫入 FILE * fp = fopen(file_name, "wb"); //windows下是"wb",表示打開一個只寫的二進制文件 if (NULL == fp) { printf("File: %s Can Not Open To Write\n", file_name); system("pause"); exit(1); } else { memset(buffer, 0, BUFFER_SIZE); int length = 0; while ((length = recv(c_Socket, buffer, BUFFER_SIZE, 0)) > 0) { if (fwrite(buffer, sizeof(char), length, fp) < length) { printf("File: %s Write Failed\n", file_name); break; } memset(buffer, 0, BUFFER_SIZE); } printf("Receive File: %s From Server Successful!\n", file_name); } fclose(fp); closesocket(c_Socket); //釋放winsock庫 WSACleanup(); system("pause"); return 0; }
轉載:腳本之家
使用select

#include<stdlib.h> #include<WINSOCK2.H> #include <windows.h> #include <process.h> #include<iostream> #include<string> using namespace std; #define BUF_SIZE 64 #pragma comment(lib,"WS2_32.lib") void recv(PVOID pt) { SOCKET sHost = *((SOCKET *)pt); while (true) { char buf[BUF_SIZE];//清空接收數據的緩沖區 memset(buf, 0, BUF_SIZE); int retVal = recv(sHost, buf, sizeof(buf), 0); if (SOCKET_ERROR == retVal) { int err = WSAGetLastError(); //無法立即完成非阻塞Socket上的操作 if (err == WSAEWOULDBLOCK) { Sleep(1000); printf("\nwaiting reply!"); continue; } else if (err == WSAETIMEDOUT || err == WSAENETDOWN || err == WSAECONNRESET)//已建立連接 { printf("\nrecv failed!"); closesocket(sHost); WSACleanup(); return; } } Sleep(100); printf("\n%s", buf); //break; } } int main() { WSADATA wsd; SOCKET sHost; SOCKADDR_IN servAddr;//服務器地址 int retVal;//調用Socket函數的返回值 char buf[BUF_SIZE]; //初始化Socket環境 if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) { printf("WSAStartup failed!\n"); return -1; } sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //設置服務器Socket地址 servAddr.sin_family = AF_INET; servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //在實際應用中,建議將服務器的IP地址和端口號保存在配置文件中 servAddr.sin_port = htons(6000); //計算地址的長度 int sServerAddlen = sizeof(servAddr); //調用ioctlsocket()將其設置為非阻塞模式 int iMode = 1; retVal = ioctlsocket(sHost, FIONBIO, (u_long FAR*)&iMode); if (retVal == SOCKET_ERROR) { printf("ioctlsocket failed!"); WSACleanup(); return -1; } //循環等待 while (true) { //連接到服務器 retVal = connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr)); if (SOCKET_ERROR == retVal) { int err = WSAGetLastError(); //無法立即完成非阻塞Socket上的操作 if (err == WSAEWOULDBLOCK || err == WSAEINVAL) { Sleep(1); printf("check connect!\n"); continue; } else if (err == WSAEISCONN)//已建立連接 { break; } else { printf("connection failed!\n"); closesocket(sHost); WSACleanup(); return -1; } } } unsigned long threadId = _beginthread(recv, 0, &sHost);//啟動一個線程接收數據的線程 while (true) { //向服務器發送字符串,並顯示反饋信息 printf("input a string to send:\n"); std::string str; //接收輸入的數據 std::cin >> str; //將用戶輸入的數據復制到buf中 ZeroMemory(buf, BUF_SIZE); strcpy(buf, str.c_str()); if (strcmp(buf, "quit") == 0) { printf("quit!\n"); break; } while (true) { retVal = send(sHost, buf, strlen(buf), 0); if (SOCKET_ERROR == retVal) { int err = WSAGetLastError(); if (err == WSAEWOULDBLOCK) { //無法立即完成非阻塞Socket上的操作 Sleep(5); continue; } else { printf("send failed!\n"); closesocket(sHost); WSACleanup(); return -1; } } break; } } return 0; }

#include <WinSock2.h> #include <Windows.h> #include <MSWSock.h> #include <stdio.h> #include <map> using namespace std; #pragma comment(lib,"Ws2_32.lib") #pragma comment(lib,"Mswsock.lib") int main() { WSAData wsaData; if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)) { printf("初始化失敗!%d\n", WSAGetLastError()); Sleep(5000); return -1; } USHORT nport = 6000; SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); u_long ul = 1; ioctlsocket(sListen, FIONBIO, &ul); sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(nport); sin.sin_addr.S_un.S_addr = ADDR_ANY; if (SOCKET_ERROR == bind(sListen, (sockaddr*)&sin, sizeof(sin))) { printf("bind failed!%d\n", WSAGetLastError()); Sleep(5000); return -1; } listen(sListen, 5); //1)初始化一個套接字集合fdSocket,並將監聽套接字放入 fd_set socketSet; FD_ZERO(&socketSet); FD_SET(sListen, &socketSet); TIMEVAL time = { 1, 0 }; char buf[4096]; fd_set readSet; FD_ZERO(&readSet); fd_set writeSet; FD_ZERO(&readSet); while (true) { //2)將fdSocket的一個拷貝fdRead傳給select函數 readSet = socketSet; writeSet = socketSet; //同時檢查套接字的可讀可寫性。 int nRetAll = select(0, &readSet, &writeSet, NULL, NULL/*&time*/);//若不設置超時則select為阻塞 if (nRetAll >0) //-1 { //是否存在客戶端的連接請求。 if (FD_ISSET(sListen, &readSet))//在readset中會返回已經調用過listen的套接字。 { if (socketSet.fd_count < FD_SETSIZE) { sockaddr_in addrRemote; int nAddrLen = sizeof(addrRemote); SOCKET sClient = accept(sListen, (sockaddr*)&addrRemote, &nAddrLen); if (sClient != INVALID_SOCKET) { FD_SET(sClient, &socketSet); printf("\n接收到連接:(%s)", inet_ntoa(addrRemote.sin_addr)); } } else { printf("連接數量已達上限!\n"); continue; } } for (int i = 0; i<socketSet.fd_count; i++) { if (FD_ISSET(socketSet.fd_array[i], &readSet)) { //調用recv,接收數據。 int nRecv = recv(socketSet.fd_array[i], buf, 4096, 0); if (nRecv > 0) { buf[nRecv] = 0; printf("\nrecv %d : %s", socketSet.fd_array[i], buf); } } if (FD_ISSET(socketSet.fd_array[i], &writeSet)) { //調用send,發送數據。 char buf[] = "hello!"; int nRet = send(socketSet.fd_array[i], buf, strlen(buf) + 1, 0); if (nRet <= 0) { if (GetLastError() == WSAEWOULDBLOCK) { //do nothing } else { closesocket(socketSet.fd_array[i]); FD_CLR(socketSet.fd_array[i], &socketSet); } } else { printf("\nsend hello!"); } } } } else if (nRetAll == 0) { printf("time out!\n"); } else { printf("select error!%d\n", WSAGetLastError()); Sleep(5000); break; } Sleep(1000); } closesocket(sListen); WSACleanup(); }