0);}}}}return 0;} 服务器的主要步骤: 1.创建监听套接字

时间:2021-09-30 04:59:02

1.选择(select)模型:
选择模型:通过一个fd_set调集打点套接字,在满足套接字需求后,通知套接字。让套接字进行事情。制止套接字进入梗阻模式,进行无谓的期待。选择模型的核心的FD_SET调集和select函数。通过该函数,我们可以们判断套接字上是否存在数据,或者能否向一个套接字写入数据。

用途如果我们想接受多个SOCKET的数据,该怎么措置惩罚惩罚呢?

由于当前socket是梗阻的,直接措置惩罚惩罚是必然完成不了要求的

a.我们会想到多线程,简直可以解决线程的梗阻问题,但斥地大量的线程并不是什么好的选择;

b我们可以想到用ioctlsocket()函数把socket设置成非梗阻的,然后用循环逐个socket检察当前套接字是否有数据,轮询进行。

这种是可以解决问题的,但是会导致频繁切换状态到内核去检察是否有数据达到,浪费时间。

c.于是想步伐用只切换一次状态就知道所有socket的接受缓冲区是否有数据,于是有了select模型

2.select函数:
int select(
    int nfds,//忽略,只是为了连结与早期的Berkeley套接字应用措施的兼容

    fd_set FAR* readfds,//可读性查抄(有数据可读入,连接*,重设,,终止)
    fd_set FAR* writefds,//可写性查抄(有数据可发出)
    fd+set FAR* exceptfds,//带外数据查抄(带外数据)
    const struct timeval FAR* timeout//超时
    );


3.select模型的事情法式:
(1)界说一个调集fd_set并初始化为空

(2)把套接字插手到fd_set调集

(3)查抄套接字的可读写性
(4)查抄套接字是否还在fd_set调集上
(5)措置惩罚惩罚数据

bool UDPNet::SelectSocket() { timeval tv; tv.tv_sec =0; tv.tv_usec = 100; fd_set fdsets;//创建调集 FD_ZERO(&fdsets); //初始化调集 FD_SET(m_socklisten,&fdsets);//将socket插手到调集中(此例子是一个socket),将多个socket插手时,可以用数组加for循环 select(NULL,&fdsets,NULL,NULL,&tv);//只查抄可读性,即fd_set中的fd_read进行操纵 if(!FD_ISSET(m_socklisten,&fdsets))//查抄 s是否s e t调集的一名成员;如答案是必定的是,则返回 T R U E。 { return false; } return true; }

4.select函数参数详解:  

三个 fd_set参数:一个用于查抄可读性(readfds),一个用于查抄可写性(writefds),另一个用于例外数据( excepfds)。

从根柢上说,fdset数据类型代表着一系列特定套接字的调集。此中,

readfds调集包孕切合下述任何一个条件的套接字:

■ 有数据可以读入。
■ 连接已经*、重设或中止。
■ 假如已挪用了listen,而且一个连接正在成立,那么accept函数挪用会告成。

writefds调集包孕切合下述任何一个条件的套接字:

■ 有数据可以发出。
■ 如果已完成了对一个非锁定连接挪用的措置惩罚惩罚,连接就会告成。
最后,exceptfds调集包孕切合下述任何一个条件的套接字:
■ 假如已完成了对一个非锁定连接挪用的措置惩罚惩罚,连接测验考试就会掉败。
■ 有带外(out-of-band,OOB)数据可供读取。

最后一个参数timeout:

对应的是一个指针,它指向一个timeval布局,用于决定select最多期待 I / O操纵完成多久的时间。

如 timeout是一个空指针,那么select挪用会无限期地“锁定”或搁浅下去,直到至少有一个描述符切合指定的条件后结束。

对timeval布局的界说如下:

struct timeval {
long tv_sec;
long tv_usec;

} ;

若将超时值设置为(0,0),表白select会当即返回,允许应用措施对 select操纵进行“轮询”。出于对性能方面的考虑,应制止这样的设置。

select告成完成后,会在 fd_set布局中,返回恰好有未完成的I/O操纵的所有套接字句柄的总量。

若赶过timeval设定的时间,便会返回0。

如何测试一个套接字是否“可读”?

必需将本身的套接字增添到readfds调集,再期待select函数完成。

select完成之后,必需判断本身的套接字是否仍为readfds调集的一部分。若答案是必定的,便表白该套接字“可读”,可当即着手从它上面读取数据。