代码注释:《使用select处理多个连接的回射服务器

针对该文章的代码进行了注释,方便理解

《Linux网络编程(3)使用select处理多个连接的回射服务器》

.https://blog.csdn.net/simmerlee/article/details/45950851


#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <string.h>
#include <string>
#include <set>
#include <map>
#include <iostream>
#include <select.h>

using namespace std;

#define BUFFER_SIZE 1024

int getSetMax(set<int>& s)
{
	if (s.empty() == true)
		return 0;
	int max = (*(s.begin()));
	set<int>::iterator it;
	for (it = s.begin(); it != s.end(); it++)
		if ((*it) > max)
			max = (*it);
	return max;
}

int getMapMax(map<int, string>& m)
{
	if (m.empty() == true)
		return 0;
	map<int, string>::iterator it;
	int max = m.begin()->first;
	for (it = m.begin(); it != m.end(); it++)
		if (it->first > max)
			max = it->first;
	return max;
}

int main(int argc, char** argv)
{
	if (argc != 2)
	{
		cout << "Usage:" << endl << argv[0] << " <port>" << endl;
		return 0;
	}
	char buffer[BUFFER_SIZE];
	int socketFd, clientFd;
	unsigned int clientAddrLength;
	int receivedLength;
	struct sockaddr_in myAddr;
	struct sockaddr_in clientAddr;
	fd_set readSet;
	fd_set writeSet;
	set<int> socketSet;
	map<int, string> receivedMessages;

	memset(&myAddr, 0, sizeof(myAddr));
	myAddr.sin_family = AF_INET;
	myAddr.sin_port = htons(atoi(argv[1]));
	myAddr.sin_addr.s_addr = htonl(INADDR_ANY);

	socketFd = socket(AF_INET, SOCK_STREAM, 0);
	bind(socketFd, (struct sockaddr*)&myAddr, sizeof(myAddr));
	listen(socketFd, 8);

	//创建set和map相应的迭代器 用于遍历set和map
	set<int>::iterator it;
	map<int, string>::iterator mapIt;
	while (true)
	{
		FD_ZERO(&readSet);
		FD_SET(socketFd, &readSet);
		for (it = socketSet.begin(); it != socketSet.end(); it++)
			FD_SET((*it), &readSet);
		//检查是否有可读数据、连接接入
		select(max(getSetMax(socketSet), socketFd) + 1, &readSet, NULL, NULL, NULL);
		if (FD_ISSET(socketFd, &readSet))//检查Socket是否有client接入
		{
			clientAddrLength = sizeof(clientAddr);
			clientFd = accept(socketFd, (struct sockaddr*)&clientAddr, &clientAddrLength);
			cout << "Accept a connection: "
				+ string(inet_ntoa(clientAddr.sin_addr)) + ':'
				<< ntohs(clientAddr.sin_port) << endl;
			socketSet.insert(clientFd);//socketSet增加新接入client
		}
		//遍历所有client连接,处理接收到的数据
		for (it = socketSet.begin(); it != socketSet.end(); it++)
		{
			if (FD_ISSET((*it), &readSet))
			{
				receivedLength = recv((*it), buffer, BUFFER_SIZE, 0);
				//通过receivedLengt判断连接是否断开
				if (receivedLength <= 0)
				{
					shutdown((*it), SHUT_RDWR);
					socketSet.erase(*it);
					receivedMessages.erase(*it);//删除对应的元素
				}
				else
				{
					buffer[receivedLength] = '\0';
					cout << "Receive a message: " << buffer << endl;
					receivedMessages[*it].append(string(buffer, receivedLength));//消息存储添加到对应的元素后
				}
			}
		}
		//处理接收数据,并回复
		if (receivedMessages.empty() == false)
		{
			FD_ZERO(&writeSet);
			//遍历所有接收数据,对应的FD加入writeSet
			for (mapIt = receivedMessages.begin(); mapIt != receivedMessages.end(); mapIt++)
			{
				FD_SET(mapIt->first, &writeSet);
			}
			//检查对应set是否可写
			select(getMapMax(receivedMessages) + 1, NULL, &writeSet, NULL, NULL);
			//遍历所有收到数据的client
			for (mapIt = receivedMessages.begin();mapIt != receivedMessages.end(); mapIt++)
			{
				//数据可写,发送数据
				if (FD_ISSET(mapIt->first, &writeSet))
				{
					send(mapIt->first, mapIt->second.c_str(), mapIt->second.length(), 0);
					receivedMessages.erase(mapIt);
				}
			}
		}
	}

	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值