网络IO模型之select
将需要查看的套接字加入到集合中,将集合交给select管理,select在内核中查看一段时间,将发生网络事件的套接字留在集合中,校验集合。
实现步骤:
1.定义集合 fd_set
2.清空集合 FD_ZERO()
3.将socket加入到集合中FD_SET
4.将集合交给select管理 select()
5.校验集合 FD_ISSET()
特点:
select:单线程处理多个客户端
1.跨平台 windows linux
2.简单 方便
3.个数限制:windows 默认64 最大 1024
linux 默认1024
4.在内核中查看客户端时会造成阻塞并且会有微秒的延迟。没有解决将数据从内核拷贝到用户区的阻塞问题。仍然是阻塞模型
#include <QCoreApplication>
#include <winsock2.h>
#include <windows.h> //winsock.h
#include <iostream>
#include <QDebug>
using namespace std;
#define MAX_PAGE 4096
#define MAX_NUM 64 //select机制在windows系统下,单次查看有上限 64
int m_nSocketNum=0;
SOCKET m_SocketEwaiter[MAX_NUM];
fd_set m_fdset;//select 定义集合
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
int nRecvNum;
char szbuf[1024] = {0};
fd_set fdtemp;
timeval tv;
tv.tv_sec = 0;//秒
tv.tv_usec = 100;//微秒
while(1){
fdtemp = m_fdset;//1.2.3
//将集合交给select管理
select(0,&fdtemp,0,0,&tv);//2
//校验结果
for (unsigned int i=0;i<m_fdset.fd_count;i++){
if (FD_ISSET(m_fdset.fd_array[i],&fdtemp))
{
nRecvNum = recv(m_fdset.fd_array[i],szbuf,sizeof(szbuf),0);
if(nRecvNum >0)
{
cout<<szbuf<<endl;
}
}
}
}
return 0;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//1.选择种类 火锅 韩餐 烤肉--
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2)
{
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The Winsock 2.2 dll was found okay\n");
FD_ZERO(&m_fdset);//2.select清空集合
//2.雇个店长--
SOCKET sock = socket(AF_INET,SOCK_STREAM,0);
if(sock == INVALID_SOCKET)
{
WSACleanup();
return 1;
}
//3.找个地方
sockaddr_in addrserver;
addrserver.sin_family = AF_INET;
addrserver.sin_port = htons(8899);
addrserver.sin_addr.S_un.S_addr = 0;
if(SOCKET_ERROR == bind(sock,(const sockaddr *)&addrserver,sizeof(addrserver)))
{
closesocket(sock);
WSACleanup();
return 1;
}
//4.店长宣传
if(SOCKET_ERROR == listen(sock,10))
{
closesocket(sock);
WSACleanup();
return 1;
}
//5.拉着客人进店 ,将客人交给服务员
//同步阻塞+多线程模型:实现与多个客户端通信 浪费资源
//如何实现单线程与多个客户端进行通信:非阻塞模型 效率低
HANDLE handle =CreateThread(0,0,&ThreadProc,0,0,0);
if(handle)
{
CloseHandle(handle);
handle =NULL;
}
while(1)
{
//阻塞
SOCKET sockWaiter = accept(sock,0,0);
if (sockWaiter!=INVALID_SOCKET){
//select-3.加入集合
FD_SET(sockWaiter,&m_fdset);
}
//8.下班--
closesocket(sock);
//9.关店--
WSACleanup();
return a.exec();
}
这篇博客介绍了在网络编程中如何使用select模型实现在Windows环境下,单线程处理多个客户端的网络事件。通过创建套接字集合,利用select函数监听客户端连接,并非阻塞地接收数据,展示了简单的跨平台网络I/O多路复用技术。

被折叠的 条评论
为什么被折叠?



