当前位置:  技术问答>linux和unix

套接字I/O模型 请教

    来源: 互联网  发布时间:2015-10-28

    本文导语:  在windows的socket编程有 select模型, WSAAsyncSelect ,WSAEventSelect , 重叠模型,完成端口模型 等几种IO模型 特别是重叠模型,完成端口模型基本指针对  服务器在任何给定的时间,都会有大量的处理,简单点就是说在性...

在windows的socket编程有
select模型, WSAAsyncSelect ,WSAEventSelect , 重叠模型,完成端口模型
等几种IO模型

特别是重叠模型,完成端口模型基本指针对 
服务器在任何给定的时间,都会有大量的处理,简单点就是说在性能上得到提高。

但是看了一下linux下面的网络编程,好像没有这方面的介绍
本人初学,可能孤陋寡闻了

|
非阻塞通信方法:
将文件管道通过fcntl()设为非阻塞通信方式,每隔一端时间对他们实行一次轮询,以判断是否可以进行读写操作。这种方式的缺点是费用太高,大部分资源浪费在轮询上。 
子进程方法:
应用多个子进程,每一个对一个单工阻塞方式通信。所有子进程通过IPC和父进程进行通信。父进程掌管所有信息。这种方式的缺点是实现复杂,而且由于IPC在各个操作系统平台上并不完全一致,会导致可移植性降低。 
信号驱动(SIGIO)的异步I/O方法:
首先,异步I/O是基于信号机制的,并不可靠。其次单一的信号不足以提供更多的信息来源。还是需要辅助以其他的手段,实现上有很高的难度。 
select ()方法:
在BSD中提供了一种可以对多路I/O进行阻塞式查询的方法--select()。它提供同时对多个I/O描述符进行阻塞式查询的方法,利用它,我们可以很方便的实现多路复用。根据统一UNIX规范的协议,POSIX也采用了这种方法,因此,我们可以在大多数操作系统中使用select方法。 
使用专门的I/O多路复用器:
在"UNIX SYSTEM V Programmer's Guide: STREAMS"一书中详细的说明了构造和使用多路复用器的方法。这里就不再详述了。
我们下面分别讨论多路I/O的两种实现方法: 
1. 非阻塞通信方法 
对一个文件描述符指定的文件或设备, 有两种工作方式: 阻塞与非阻塞。所谓阻塞方式的意思是指, 当试图对该文件描述符进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待状态, 直到有东西可读或者可写为止。而对于非阻塞状态, 如果没有东西可读, 或者不可写, 读写函数马上返回, 而不会等待。缺省情况下, 文件描述符处于阻塞状态。在实现聊天室时, server 需要轮流查询与各client 建立的 socket, 一旦可读就将该 socket 中的字符读出来并向所有其他client 发送。并且, server 还要随时查看是否有新的 client 试图建立连接,这样, 如果 server 在任何一个地方阻塞了, 其他 client 发送的内容就会受到影响,得不到服务器的及时响应。新 client 试图建立连接也会受到影响。所以我们在这里不能使用缺省的阻塞的文件工作方式,而需要将文件的工作方式变成非阻塞方式。
在UNIX下,函数fcntl()可以用来改变文件I/O操作的工作方式,函数描述如下: 
fcntl( sockfd, F_SETFL, O_NONBLOCK); 
// sockfd 是要改变状态的文件描述符。 
// F_SETFL 表明要改变文件描述符的状态 
// O_NONBLOCK 表示将文件描述符变为非阻塞的。 
为了节省篇幅我们使用自然语言描述聊天室 server : 
while ( 1) { 
if 有新连接 then 建立并记录该新连接; 
for ( 所有的有效连接) 
begin 
if 该连接中有字符可读 then 
begin 
读入字符串; 
for ( 所有其他的有效连接) 
begin 
将该字符串发送给该连接; 
end; 
end; 
end; 
end。 

|
由于判断是否有新连接, 是否可读都是非阻塞的, 因此每次判断,不管有还是没有, 都会马上返回。 这样,任何一个 client 向 server 发送字符或者试图建立新连接, 都不会对其他 client 的活动造成影响。 
对 client 而言, 建立连接之后, 只需要处理两个文件描述符, 一个是建立了连接的 socket 描述符, 另一个是标准输入和 server 一样, 如果使用阻塞方式的话, 很容易因为其中一个暂时没有输入而影响另外一个的读入。因此将它们都变成非阻塞的, 然后client 进行如下动作: 
while ( 不想退出) 
begin 
if ( 与 server 的连接有字符可读) 
begin 
从该连接读入, 并输出到标准输出上去。 
End; 
if ( 标准输入可读) 
Begin 
从标准输入读入, 并输出到与 server 的连接中去。 
End; 
End。 
上面的读写分别调用这样两个函数: 
read( userfd[i], line, MAX_LINE); 
// userfd[i] 是指第 i 个 client 连接的文件描述符。 
// line 是指读出的字符存放的位置。 
// MAX_LINE 是一次最多读出的字符数。 
// 返回值是实际读出的字符数。 
write( userfd[j], line, strlen( line)); 
// userfd[j] 是第 j 个 client 的文件描述符。 
// line 是要发送的字符串。 
// strlen( line) 是要发送的字符串长度。 
分析上面的程序可以知道, 不管是 server 还是 client, 它们都不停的轮流查询各个文件描述符, 一旦可读就读入并进行处理。 这样的程序, 不停的在执行, 只要有CPU 资源, 就不会放过。因此对系统资源的消耗非常大。server 或者 client 单独执行时, CPU 资源的 98% 左右都被其占用。极大的消耗了系统资源。 
因此,虽然我们不希望在某一个用户没有反应时阻塞其他的用户,但我们却应该在没有任何用户有反应的情况之下停止程序的运行,让出抢占的系统资源,进入阻塞状态。有没有这种方法呢?现在的UNIX系统中都提供了select方法,具体实现方式如下: 
使用 select 判断一组文件描述符中是否有一个可读(写), 如果没有就阻塞, 直到有一个的时候就被唤醒。select 方法中, 所有文件描述符都是阻塞的。我们先看比较简单的 client 的实现: 
由于 client 只需要处理两个文件描述符, 因此, 需要判断是否有可读写的文件描述符只需要加入两项: 
FD_ZERO( sockset); 
// 将 sockset 清空 
FD_SET( sockfd, sockset); 
// 把 sockfd 加入到 sockset 集合中 
FD_SET( 0, sockset); 
// 把 0 (标准输入) 加入到 sockset 集合中 
然后 client 的处理如下: 
while ( 不想退出) { 
select( sockfd+1, &sockset, NULL, NULL, NULL); 
// 此时该函数将阻塞直到标准输入或者 sockfd 中有一个可读为止 
// 第一个参数是 0 和 sockfd 中的最大值加一 
// 第二个参数是 读集, 也就是 sockset 
// 第三, 四个参数是写集和异常集, 在本程序中都为空 
// 第五个参数是超时时间, 即在指定时间内仍没有可读, 则出错 
// 并返回。 当这个参数为NULL 时, 超时时间被设置为无限长。 
// 当 select 因为可读返回时, sockset 中包含的只是可读的 
// 那些文件描述符。 
if ( FD_ISSET( sockfd, &sockset)) { 
// FD_ISSET 这个宏判断 sockfd 是否属于可读的文件描述符 
从 sockfd 中读入, 输出到标准输出上去。 

if ( FD_ISSET( 0, &sockset)) { 
// FD_ISSET 这个宏判断 sockfd 是否属于可读的文件描述符 
从标准输入读入, 输出到 sockfd 中去。 

重新设置 sockset。 (即将 sockset 清空, 并将 sockfd 和 0 加入) 

下面看 server 的情况: 
设置 sockset 如下: 
FD_ZERO( sockset); 
FD_SET( sockfd, sockset); 
for ( 所有有效连接) 
FD_SET( userfd[i], sockset); 

maxfd = 最大的文件描述符号 + 1; 
server 处理如下: 
while ( 1) { 
select( maxfd, &sockset, NULL, NULL, NULL); 
if ( FD_ISSET( sockfd, &sockset)) { 
// 有新连接 
建立新连接, 并将该连接描述符加入到 sockset 中去了。 

for ( 所有有效连接) { 
if ( FD_ISSET ( userfd[i], &sockset)) { 
// 该连接中有字符可读 
从该连接中读入字符, 并发送到其他有效连接中去。 


重新设置 sockset; 

性能比较 
由于采用 select 机制, 因此当没有字符可读时, 程序处于阻塞状态,最小程度的占用CPU 资源, 在同一台机器上执行一个 server 和若干个client 时, 系统负载只有 0。1 左右, 而采用原来的非阻塞通信方法, 只运行一个 server, 系统负载就可以达到 1。5 左右。 因此我们推荐使用 select。

------------------------------------
努力学习xslt中...

|
你看看那本经典书籍  unix网络编程   上面就谈到了i/o模型。

好像有5种I/O模型吧。
大概有这几种方法:
select/poll/epoll/AIO/SIGIO
如果是BSD类型的UNIX,还有Kqueue

|
我这有两个自己写的学习用的程序,你需要的话可以发给你,留下你的e-mail
------------------------------------
努力学习xslt中...

|
linux有poll,epoll

|
poll和select在某些系统上面是等价的(仅仅是接口不一样,实现代码根本就是一个东西)

立即返回的是非阻塞式socket,这个和select配合起来才能真正起作用,对于阻塞式socket,select可以说是没有意义的。

send、和recv属于慢速调用,没有数据的时候会死等……

|
对于阻塞式socket,select可以说是没有意义的。
--------------------------------------------
这好像不对吧。
对于select管理多个socket时,不管这些socket是否阻塞还是不阻塞的,
select都是为了知道有读或写的事件发生,然后再决定要对那个socket读或写,
这至少比轮讯每个socket有效率多了。
linux下除了select还有epoll,听说比select的效率高许多。

    
 
 

您可能感兴趣的文章:

  • TCP连接中创建的监听描述字和已连接描述字(套接字)对应的是同一个套接口么,如果是的话,读写数据时系统怎么区分是哪个套接字的?
  • 监听套接字listenfd 已连接套接字connectfd 中fd什么意思
  • 请问原始套接字的绑定和一般都的套接字的绑定有什么区别吗
  • 非阻塞套接字
  • 关于linux套接字的问题
  • TCP套接字抓包的问题
  • 是否可以通过消息队列在进程之间传递套接字?
  • socket套接字群发?
  • linux下原始套接字创建失败
  • SOCKET 编程之从容关闭套接字如何实现????
  • sqlserver iis7站长之家
  • 如何判断套接字是被关闭了。
  • 请问linux下套接字读就绪产生什么信号
  • Linux下如何在普通用户下创建原始套接字(实现ping)
  • 多线程close() socket套接字的问题
  • udp套接字能否设定成非阻塞模式?
  • 套接字
  • 关于数据报套接字的使用
  • 请教高手:linux原始套接字问题
  • 请问各位大侠:如何将标准输出定位到套接字?
  • 请教套接字中的select()函数问题
  • 请教高人:同一个套接字(做客户端)连接到server后在不同子进程里使用能否不采取互斥措施收发?
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • [求助]关于unix域套接字
  • 关于子进程间共享套接字描述符的问题?
  • write函数往套接字文件描述符写入数据的时候数据存储在哪里 ?
  • 套接字是进程私有的资源吗?
  • 类unix系统编写大规模响应网络服务程序使用什么套接字模型
  • 使用原始套接字来发送一个icmp包,不适用setsockopt做控制会怎么样?
  • 请问一般套接字的绑定和原始套接字的绑定有什么区别吗
  • Unix Domain套接字的Java包 junixsocket
  • socket(套接字)怎么传输二进制数据?急
  • 高分求教:有关套接字建立ftp的问题
  • select 处理套接字文件描述符
  • 套接字中,第二个参数SOCK_RAW 与SOCK_PACKET 有什么区别
  • 如果使用套接字编程,增样控制连接超时?
  • 高分求高手赐教-关于linux下进程共享TCP套接字的问题
  • 一个未连接的客户端socket套接字在select处的奇怪行为
  • 请问在Unix/Linux上的套接字模型有那些,那些比较常用,Apache使用的是那个,谢谢?!如果能和Windows上的作对比就更好了
  • 请问在vmware虚拟机下的UBUNTU系统里,原始套接字sock_raw能否正常收发数据
  • 套接字的疑惑
  • 求助!如何使用同一个套接字和端口实现反复下载
  • 关于UDP套接字的问题


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3