首先我查阅了一些资料:这个问题的引起原因很简单…connect函数之前将socket设置成了非阻塞模式;要解决这个问题在connect之后再设置非阻塞模式即可;
但是我是个菜逼,什么阻塞非阻塞搞得云里雾里的,根本搞不明白…因此我找到了另一个内容,是一段代码
unsigned long ul = 1;ioctl(nSocket, FIOBIO. &ul);//设置为非阻塞模式
现在我就可以根据这个ioctl去配合strace去判断,到底发生了什么….
睡觉去了,明天又是需要上班的一天,很烦
—-更新
查阅了tcp/ip卷二中关于connect的描述,找到了报错原因:
soconnect方法已经返回,但是链接还没有完成,并且使能了非阻塞io
soconnect函数
这个函数的目的是确保socket处于正确的链接状态;
socket没有链接,或者链接被挂起,那么链接请求是正确的
如果socket已经链接,或者链接正在等待处理,那么新的链接将被面向链接的请求拒绝
**
当然,既然出现了EINPROGRESS错误,那就是说socennect方法并没有出现问题,出现问题的情况是连接处于正确的状态,但是链接并没有完成,并且赋能了非阻塞io
具体问题的分析
首先我在使用connect之前貌似并没有显示的将socket指定为非阻塞io;但是我设置了超时状态,难道是设置接受、发送超时让我的socket处于了非阻塞?
如果socket处在阻塞状态,那么这个问题并不会出现,因为阻塞状态下,只有当链接被正确的,整条流程才会继续向下走;因此出现这种问题的一个前提一定是socket被设置为了非阻塞的socket;
那么,为什么明明soconnect都通过了,说明socket是处在正确状态的,但是connect却没有完成?
这就需要了解一下connect的整体过程
conncet的过程
以tcp协议为例
- 开始connect
- soconnect执行;如果是非阻塞的插口(socket),那么soconnect将会调用tsleep等待链接完成
- 将socket的状态设置为soisconnecting并且开始三次握手
- 如果三次握手完成了,接下来会将socket至于soisconnected状态,然后调用wakeup来唤醒tsleep
因此connect返回EINPROGRESS并不能说是connect出错了
有可能connect并没有出错,指示因为在非阻塞状态下,链接没有及时的完成建立,此时由于是非阻塞,connect并不应当停下来(阻塞)等待connect完全建立完成,而是应当继续让程序向下执行;
所以如果一定要使用非阻塞connect,应当在connect之后进行一次判断,判断connect是否可以被使用,而不能直接对connect方法的结果进行判断;
所以,我什么时候把socket设置为非阻塞模式了??
按照我的设计,整个流程应当处于阻塞模式下,因为这个项目按道理讲并不会有很大的并发量,甚至并发情况都是很少见的;但是既然出现了EINPROGRESS,那就说明,至少在connect之前,我把这个socket设置为了非阻塞模式;到底是哪一步让socket变成了非阻塞?
在查阅资料的时候偶然间发现linux内核代码中,connect的超时和send超时使用的是同一个参数,那就是说,在设置send超时的时候,这个超时时间同时也会对connect生效;那么linux中使用setsockopt设置超时时间是如何实现的?是否由于这个设置让socket转化为了非阻塞socket?
