socket之select模式

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;
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值