windows提供了選擇(select)、異步選擇(WSAAsyncSelect)、事件選擇(WSAEventSelect)、重疊I /O(overlapped I/O)和完成端口(completion port)。
用戶端:
#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "WS2_32.lib")
const unsigned int PORT = 11024;
const int kBufferSize = 1024;
int main() {
WSADATA wsData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsData);
if(iResult != NO_ERROR) {
std::cout << "start up failed" << std::endl;
return -1;
}
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //set tcp
if(s == INVALID_SOCKET) {
std::cout << "Error socket" << std::endl;
WSACleanup();
return -1;
}
SOCKADDR_IN addIn;
addIn.sin_port = htons(PORT);
addIn.sin_family = AF_INET;
addIn.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//-----------------------------------
int iMode = 1;
ioctlsocket(s, FIONBIO, (u_long FAR *)&iMode); // set the mode is the unblock
connect(s, (LPSOCKADDR)&addIn, sizeof(addIn));
char cSendBuffer[kBufferSize];
std::cout << "Tell the Server: ";
std::cin >> cSendBuffer;
int iSendRet = send(s, cSendBuffer, kBufferSize, 0);
char cRecnBuffer[kBufferSize] = "";
int iRecvRet = 0;
while(true)
{
if ((iRecvRet = recv(s, cRecnBuffer, kBufferSize, 0)) > 0)
{
std::cout << "recvive information from server: " << cRecnBuffer << std::endl;
std::cout << "Tell the Server: ";
std::cin >> cSendBuffer;
send(s, cSendBuffer, kBufferSize, 0);
}
}
closesocket(s);
WSACleanup();
return 0;
}
服務端:
#include <iostream>
#include <winsock2.h>
#pragma comment(lib, "WS2_32.lib")
const unsigned int PORT = 11024;
const int kBufferSize = 1024;
int g_ClientCount = 0;
SOCKET g_ClientSocket[FD_SETSIZE];
unsigned long WINAPI WorkerThread(void *p);
int main() {
WSADATA wsaData;
if(WSAStartup(2, &wsaData) != 0) {
std::cout << "start up failed" << std::endl;
return -1;
}
SOCKET sev = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if(sev == SOCKET_ERROR) {
std::cout << "create the socket failed" << std::endl;
return -1;
}
SOCKADDR_IN addIn;
addIn.sin_port = htons(PORT);
addIn.sin_family = AF_INET;
addIn.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int ibRet = bind(sev, (LPSOCKADDR)&addIn, sizeof(addIn));
if(ibRet != 0) {
std::cout << "bind failed" << std::endl;
return -1;
}
int iLRet = listen(sev, 10);
if(iLRet != 0) {
std::cout << "Listen failed " << std::endl;
return -1;
}
SOCKET acceptSocket;
int iLen = sizeof(addIn);
unsigned long arg = 1;
ioctlsocket(sev, FIONBIO, &arg);
HANDLE threadHandle = CreateThread(NULL, 0, WorkerThread, NULL, 0, 0);
while(true) {
acceptSocket = accept(sev, (LPSOCKADDR)&addIn, &iLen);
if(acceptSocket != SOCKET_ERROR) {
g_ClientSocket[g_ClientCount++] = acceptSocket;
}
}
for(int i = 0; i < g_ClientCount; ++i) {
closesocket(g_ClientSocket[i]); //clear the socket connect
}
CloseHandle(threadHandle); // close the thread
return 0;
}
unsigned long WINAPI WorkerThread(void *p) {
FD_SET read;
timeval limitTime = {1, 0};
char Message[kBufferSize];
Message[0] = '\0';
while(true) {
FD_ZERO(&read);
for(int i = 0; i < g_ClientCount; ++i) {
FD_SET(g_ClientSocket[i], &read);
}
int iRet = select(0, &read, NULL, NULL, &limitTime);
if(iRet == 0) {// time out
continue;
}
for(int i = 0; i < g_ClientCount; ++i) {
if(FD_ISSET(g_ClientSocket[i], &read)) {
int iRecv = recv(g_ClientSocket[i], Message, kBufferSize, 0);
if(iRecv == 0 || (iRecv == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)) {
closesocket(g_ClientSocket[i]);
//after the current socket that will go befor one step
g_ClientSocket[i--] = g_ClientSocket[--g_ClientCount]; // the total will decrease;
} else {
if(iRecv > 0) {
std::cout << "Server Receive the data is: " << Message << std::endl;
std::cout << "Input the send Message: ";
std::cin >> Message;
send(g_ClientSocket[i], Message, kBufferSize, 0);
}
}
}
}
}
return 0;
}