织梦CMS - 轻松建站从此开始!

罗索

非阻塞connect()和accept()

落鹤生 发布于 2011-02-16 14:29 点击:次 
非阻塞方式实现Socket的connect()和accept()
TAG:

一.select()函数
    select()函数准备好读的条件:
    1>.套接口有数据可读
    2>.该连接的读这一半关闭(也就是接收了FIN的TCP连接)。对这样的套接口进行读操作将不阻塞并返回0(也就是返回EOF)。
    3>.该套接口是一个侦听套接口且已完成的连接数不为0。
    4>.其上有一个套接口错误待处理,对这样的套接口的读操作将不阻塞并返回-1,并设置errno,可以通过设置SO_ERROR选项调用getsockopt函数获得。

    select()函数准备好写的条件:
    1>.套接口有可用于写的空间。
    2>.该连接的写这一半关闭,对这样的套接口进行写操作将产生SIGPIPE信号。
    3>.该套接口使用非阻塞的方式connect建立连接,并且连接已经异步建立,或则connect已经以失败告终。
    4>.其上有一个套接口错误待处理。

二.accept()函数

1.阻塞模式

阻塞模式下调用accept()函数,而且没有新连接时,进程会进入睡眠状态。

2.非阻塞模式

非阻塞模式下调用accept()函数,而且没有新连接时,将返回EWOULDBLOCK错误。

非阻塞模式select() + accept() 

 

  1. sockfd = listen_tcp(); //socket()、bind()、listen() 
  2. FD_SET(sockfd, rset); 
  3. while(1){ 
  4. // 等待某个事件发生:或是新连接、或是数据、或是FIN、或是RST到达  
  5. ret = select(sockfd + 1, rset, NULL, NULL, timeout);
  6. if(select()返回TIMEOUT){ //select()超时
  7. printf("日志打印");
  8. sleep(1);
  9. continue;
  10. }
  11. else if(FD_ISSET(sockfd,&rset)){//判断句柄是否可读,返回真代表可读,可读代表有新连接。 
  12. connfd = accept(sockfd, ...); 
  13. else if(select()返回错误){ 
  14. return -1; 
  15.  
  16. pthread_create(thread_recv_data, connfd, ...); // 创建线程处理新连接. 
  17.  
  18. close(); 
  19.  

三.connect()函数

1.阻塞模式

客户端调用connect()函数将激发TCP的三路握手过程,但仅在连接建立成功或出错时才返回。返回的错误可能有以下几种情况:

    1>.如果TCP客户端没有接收到SYN分节的响应,则返回ETIMEDOUT,阻塞模式的超时时间在75秒(4.4BSD内核)到几分钟之间。

    2>.如果对客户的SYN的响应时RST,则表明该服务器主机在我们指定的端口上没有进程在等待与之连接(例如服务器进程也许没有启动),这称为硬错,客

户一接收到RST,马上就返回错误ECONNREFUSED.

    3>.如果某客户发出的SYN在中间的路由器上引发了一个目的地不可达ICMP错误,多次尝试发送失败后返回错误号为EHOSTUNREACH或ENETUNREACH.

附加:产生RST的三种情况,一是SYN到达某端口但此端口上没有正在侦听的服务器、二是TCP想取消一个已有连接、三是TCP接收了一个根本不存在的连接上的

分节。

2.非阻塞工作模式

调用connect()函数会立刻返回EINPROCESS错误,但TCP通信的三路握手过程正在进行,所以可以使用select函数来检查这个连接是否建立成功。

    源自Berkeley的实现有两条与select函数和非阻塞相关的规则:

1>.当连接成功建立时,描述字变成可写。

2>.当连接建立出错时,描述字变成即可读又可写。getsockopt()函数的errno == 0表示只可写。

非阻塞模式 select() + connect()

 

  1. while(1){ 
  2. ret = connect(); 
  3. if(errno == EINPROCESS){ //此时TCP的三路握手继续进行 
  4. select(...) //等待某个事件发生:或是新连接、或是超时 
  5. if(FD_ISSET(sockfd,&wset) ){ //判断句柄可写,不能代表建立连接成功。 
  6. getsockopt(...); 
  7. if(errno == 0){  //建立连接成功 
  8. else if(select()返回TIMEOUT){ 
  9. sleep(1); 
  10. continue(); 
  11. else if(ret == -1){ 
  12. //Connect  failed 
  13. pthread_create(thread_send_log, ...); //建立线程处理新连接 
  14. close(); 
(hanchaoman)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201102/10901.html]
本文出处:CSDN博客 作者:hanchaoman
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容