一,select多路转接服务器
网络编程(三)TCP IO多路转接服务器编程(select)
二,select多路转接服务器(多线程)
前面介绍的select多路转接服务器已经可以实现处理多个客户端的服务器,为了进一步提高效率,我们还可以将上面的select多路转接服务器改写为多线程的形式。与前面普通的select多路转接服务器相比,要修改为多线程主要是要在主线程的while(1)的循环中做些处理:
在select检测完读集合过后,
1,如果检查到有监听文件描述符准备就绪,则开一个子线程让其去处理该次的连接;
2,如果检测到有通信文件描述符准备就绪,则开一个子线程让其去处理该次的通信。
注意:本次使用多线程改造该服务器的多线程方法仍然是C++11标准的跨平台方法。同时,需注意:
1,在监听文件描述符就绪以后连接客户端过程中,要添加accept成功以后返回的客户端进入待检测集合中,方便下一次的检测,所以需要传入的fd_set参数为指针类型,且该子线程与主线程detach以后,子线程与主线程在运行过程中可能同时访问该fd_set数据,所以要互斥访问。maxfd这个变量同理。也要互斥访问。
2,在处理客户端通信的子线程中,同样子线程与主线程detach,所以要注意该子线程中的fd_set数据也可能与主线程对fd_set的访问发生冲突,所以也要注意互斥访问。
关于C++11跨平台多线程编程的方法与互斥量的应用在我前面的博客中有介绍:
1)C++新特性(六)多线程(1)线程启动、结束,创建线程、join,detach,线程传参详解
2)C++新特性(六)多线程(2)线程中互斥量的使用,mutex对象使用,lock_guard类模板,死锁的解决
下面是多线程select多路转接服务器一个例子代码:
服务端
//server_thread.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <thread>
#include <mutex>
using namespace std;
mutex fdset_mutex;
mutex maxfd_mutex;
void Connection(int lfd,fd_set*rdset,int*maxfd)//监听文件描述符,待检测的读集合,集合中的最大文件描述符
{
// 接受连接请求, 这个调用不阻塞
struct sockaddr_in cliaddr;
int cliLen = sizeof(cliaddr);
int cfd = accept(lfd, (struct sockaddr*)&cliaddr, (socklen_t*)&cliLen);
// 得到了有效的文件描述符
// 通信的文件描述符添加到读集合
// 在下一轮select检测的时候, 就能得到缓冲区的状态
fdset_mutex.lock();
FD_SET(cfd, rdset);
fdset_mutex.unlock();
// 重置最大的文件描述符
maxfd_mutex.lock();
*maxfd = cfd > *maxfd ? cfd : *maxfd;
maxfd_mutex.