TCP非阻塞accept和非阻塞connect
http://blog.chinaunix.net/uid-20751538-id-238260.html
struct linger的l_onoff标志设为1,l_linger设为0。这个时候,如果关闭TCP连接时,会先在socket上发送一个RST包。这个时候会出现下面的问题:
A:select向服务器返回监听socket可读,但是服务器要在一段时间之后才能调用accept;
B:在服务器从select返回和调用accept之前,收到从客户发送过来的RST;
C:这个已经完成的连接被从队列中删除,我们假设没有其它已完成的连接存在;
D:服务器调用accept,但是由于没有其它已完成的连接存在,因而服务器被阻塞了;
注意,服务器会被一直阻塞在accept调用上,直到另外一个客户建立一个连接为止;但是如果一直没有其它客户建立连接,那么服务器将仍然一直被阻塞在accept调用上,不处理任何其他已就绪的socket;
解决这个问题的办法是:
A:如果使用select来获知何时有链接已就绪可以accept时,总是把监听socket设置为非阻塞模式,并且
B:
在后面的accept调用中忽略以下错误:EWOULDBLOCK(源自Berkeley的实现在客户放弃连接时出现的错误)、
ECONNABORTED(Posix.1g的实现在客户放弃连接时出现的错误)、EPROTO(SVR4的实现在客户放弃连接时出现的错误)和
EINTR(如果信号被捕获).
在
一个TCP套接口被设置为非阻塞之后调用connect,connect会立即返回EINPROGRESS错误,表示连接操作正在进行中,但是仍未完成;
同时TCP的三路握手操作继续进行;在这之后,我们可以调用select来检查这个链接是否建立成功;非阻塞connect有三种用途:
1.我们可以在三路握手的同时做一些其它的处理.connect操作要花一个往返时间完成,而且可以是在任何地方,从几个毫秒的局域网到几百毫秒或几秒的广域网.在这段时间内我们可能有一些其他的处理想要执行;
2.可以用这种技术同时建立多个连接.在Web浏览器中很普遍;
3.
由于我们使用select来等待连接的完成,因此我们可以给select设置一个时间限制,从而缩短connect的超时时间.在大多数实现
中,connect的超时时间在75秒到几分钟之间.有时候应用程序想要一个更短的超时时间,使用非阻塞connect就是一种方法;
非阻塞connect听起来虽然简单,但是仍然有一些细节问题要处理:
1.即使套接口是非阻塞的,如果连接的服务器在同一台主机上,那么在调用connect建立连接时,连接通常会立即建立成功.我们必须处理这种情况;
2.源自Berkeley的实现(和Posix.1g)有两条与select和非阻塞IO相关的规则:
A:当连接建立成功时,套接口描述符变成可写;
B:当连接出错时,套接口描述符变成既可读又可写;
注意:当一个套接口出错时,它会被select调用标记为既可读又可写;
非阻塞connect有这么多好处,但是处理非阻塞connect时会遇到很多可移植性问题;
处理非阻塞connect的步骤:
第一步:创建socket,返回套接口描述符;
第二步:调用fcntl把套接口描述符设置成非阻塞;
第三步:调用connect开始建立连接;
第四步:判断连接是否成功建立;
A:如果connect返回0,表示连接简称成功(服务器可客户端在同一台机器上时就有可能发生这种情况);
B:调用select来等待连接建立成功完成;
如果select返回0,则表示建立连接超时;我们返回超时错误给用户,同时关闭连接,以防止三路握手操作继续进行下去;
如果select返回大于0的值,则需要检查套接口描述符是否可读或可写;如果套接口描述符可读或可写,则我们可以通过调用getsockopt来得到套
接口上待处理的错误(SO_ERROR),如果连接建立成功,这个错误值将是0,如果建立连接时遇到错误,则这个值是连接错误所对应的errno值(比
如:ECONNREFUSED,ETIMEDOUT等).
"读取套接口上的错误"是遇
到的第一个可移植性问题;如果出现问题,getsockopt源自Berkeley的实现是返回0,等待处理的错误在变量errno中返回;但是
Solaris会让getsockopt返回-1,errno置为待处理的错误;我们对这两种情况都要处理;
这
样,在处理非阻塞connect时,在不同的套接口实现的平台中存在的移植性问题,首先,有可能在调用select之前,连接就已经建立成功,而且对方的
数据已经到来.在这种情况下,连接成功时套接口将既可读又可写.这和连接失败时是一样的.这个时候我们还得通过getsockopt来读取错误值;这是第
二个可移植性问题;
移植性问题总结:
1.对于出错的套接口描述符,getsockopt的返回值源自Berkeley的实现是返回0,待处理的错误值存储在errno中;而源自Solaris的实现是返回0,待处理的错误存储在errno中;(套接口描述符出错时调用getsockopt的返回值不可移植)
2.有可能在调用select之前,连接就已经建立成功,而且对方的数据已经到来,在这种情况下,套接口描述符是既可读又可写;这与套接口描述符出错时是一样的;(怎样判断连接是否建立成功的条件不可移植)
这样的话,在我们判断连接是否建立成功的条件不唯一时,我们可以有以下的方法来解决这个问题:
1.调用getpeername代替getsockopt.如果调用getpeername失败,getpeername返回ENOTCONN,表示连接建立失败,我们必须以SO_ERROR调用getsockopt得到套接口描述符上的待处理错误;
2.调用read,读取长度为0字节的数据.如果read调用失败,则表示连接建立失败,而且read返回的errno指明了连接失败的原因.如果连接建立成功,read应该返回0;
3.再调用一次connect.它应该失败,如果错误errno是EISCONN,就表示套接口已经建立,而且第一次连接是成功的;否则,连接就是失败的;
被中断的connect:
如
果在一个阻塞式套接口上调用connect,在TCP的三路握手操作完成之前被中断了,比如说,被捕获的信号中断,将会发生什么呢?假定connect不
会自动重启,它将返回EINTR.那么,这个时候,我们就不能再调用connect等待连接建立完成了,如果再次调用connect来等待连接建立完成的
话,connect将会返回错误值EADDRINUSE.在这种情况下,应该做的是调用select,就像在非阻塞式connect中所做的一样.然
后,select在连接建立成功(使套接口描述符可写)或连接建立失败(使套接口描述符既可读又可写)时返回.
原文地址:http://bdxnote.blog.163.com/blog/static/844423520098651256549/
TCP非阻塞accept和非阻塞connect的更多相关文章
- UNIX网络编程-非阻塞connect和非阻塞accept
1.非阻塞connect 在看了很多资料之后,我自己的理解是:在socket发起一次连接的时候,这个过程需要一段时间来将三次握手的过程走完,如果在网络状况不好或者是其他的一些情况下,这个过程需要比较长 ...
- boot asio 非阻塞同步编程---非阻塞的accept和receive。
boot asio 非阻塞同步编程---非阻塞的accept和receive. 客户端编程: #include<boost/timer.hpp> #include <iostream ...
- TCP同步与异步及阻塞模式,多线程+阻塞模式,非阻塞模式简单介绍
首先我简单介绍一下同步TCP编程 与异步TCP编程. 在服务端我们通常用一个TcpListener来监听一个IP和端口.客户端来一个请求的连接,在服务端可以用同步的方式来接收,也可以用异步的方式去接收 ...
- socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto
socket异步通信-如何设置成非阻塞模式.非阻塞模式下判断connect成功(失败).判断recv/recvfrom成功(失败).判断send/sendto 博客分类: Linux Socket s ...
- Python_阻塞IO、非阻塞IO、IO多路复用
0.承上 进程: 计算机里最小的资源分配单位: 数据隔离, 利用多核,数据不安全. 线程: 计算机中最小的CPU调度单位: 数据共享,GIL锁,数据不安全. 协程: 线程的一部分,是有用户来调度的; ...
- 事件驱动模型 IO多路复用 阻塞IO与非阻塞IO select epool
一.事件驱动 1.要理解事件驱动和程序,就需要与非事件驱动的程序进行比较.实际上,现代的程序大多是事件驱动的,比如多线程的程序,肯定是事件驱动的.早期则存在许多非事件驱动的程序,这样的程序,在需要等待 ...
- 斐讯面试记录—阻塞Socket和非阻塞Socket
文章出自:http://blog.csdn.net/VCSockets/ 1.TCP中的阻塞Socket和非阻塞Socket 阻塞与非阻塞是对一个文件描述符指定的文件或设备的两种工作方式. 阻塞的意思 ...
- 阻塞IO、非阻塞IO、同步IO、异步IO等
https://www.cnblogs.com/zingp/p/6863170.html 阅读目录 1 基础知识回顾 2 I/O模式 3 事件驱动编程模型 4 select/poll/epoll的区别 ...
- NIO 之阻塞IO和非阻塞IO(转载)
阻塞模式 IO 我们已经介绍过使用 Java NIO 包组成一个简单的客户端-服务端网络通讯所需要的 ServerSocketChannel.SocketChannel 和 Buffer,我们这里整合 ...
随机推荐
- [笔记]一个测试浏览器对html5支持的网站
用需要测试的浏览器打开这个地址:http://html5test.com/
- springboot注解
@RestController和@RequestMapping注解 我们的Example类上使用的第一个注解是 @RestController .这被称为一个构造型(stereotype)注解.它为阅 ...
- Lua与C++交互初探之Lua调用C++
Lua与C++交互初探之Lua调用C++ 上一篇我们已经成功将Lua的运行环境搭建了起来,也成功在C++里调用了Lua函数.今天我来讲解一下如何在Lua里调用C++函数. Lua作为一个轻量级脚本语言 ...
- iTween基础之功能简介
一.iTween 介绍 .二.iTween 原理.三.iTween 下载.四.iTween 类介绍.五.主要功能介绍 原文地址:http://blog.csdn.net/dingkun520wy/ar ...
- [shell基础]——整数比较;字符串比较;文件测试;逻辑测试符
整数比较方法一:[ ] 或 [[ ]] (1) 此方法需要使用整数比较运算符.[标注:equal 等于 greater 大于 less-then 小于] (2) 使用时一定要注意前后一 ...
- Delphi 调试日子 - TLogger
这段时间又开始用delphi了,才发现我对它这么的不熟悉! 简单的而有效的调试工具 Logger 这个是“榕树下”的作品,小巧而精悍.稍微调整了一下.在需要的地方加入 {$IFDEF DEBUG} ...
- C++设计模式——享元模式
本文版权归果冻说所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.如果这篇文章对你有帮助,你可以请我喝杯咖啡. » 本文链接:http:// ...
- WinForm-利用Anchor和Dock属性缩放控件
转自:http://www.cnblogs.com/tianzhiliang/articles/2144692.html 有一点让许多刚接触WinForms编程的开发者感到很棘手,就是在用户调整各种控 ...
- JavaScript + HTML DOM (keep for myself)
1.改变 HTML 输出流 JavaScript 能够创建动态的 HTML 内容 eg. <script>document.write(Date());</script> 绝对 ...
- 【转载】CreateProcess的用法
第一.第二个参数的用法: 例子: 使用ie打开指定的网页. 注意第二个参数是 可执行文件+命令行参数 #include "stdafx.h" #include <window ...