日期:2014-05-16  浏览次数:20601 次

突然发现Linux下socket的怪异之处!
有两点奇怪的地方。

第一、阻塞模式下,无accept,connect返回成功

  背景:connect运行在阻塞模式下,服务端也是阻塞的,只能接收一个客服端的请求。

  问题:服务端运行在死循环里,当接收到一个客户端连接后,accept并进入交互。此时再有一个客户端连接上来,connect返回成功,发送消息被缓存起来,等待第一个客户端退出后。服务端accept与此客户端建立连接。

  问题是都没accept,应该connect不成功才对,原因是啥?如果是listen放到缓存队列里的话,那怎么样可以不缓存,让connect直接返回失败!
   
第二、非阻塞模式下,connect均返回失败

  非阻塞模式下,本地客户端连接本地服务端,服务端accept成功,但客户端connect返回失败。远程客户端连接本地服务端,连不上。。。是何原因。代码整理之后贴出来

------解决方案--------------------
问题1:判断一个连接的成功是三次握手,三次握手成功后才进行accept。在listen的时候其实有两个队列,一个是已经完成三次握手的队列,就是连接成功,还有一个是等待三次握手的队列。所有connect成功跟有无accept无关。
问题2:当connect在非阻塞的模式下时,并没有等待三次握手的成功,所有返回失败。如果想用connect的非阻塞模式,可以配合select使用。
------解决方案--------------------
1.对于listen第二个参数的问题,有两点需要理解一下:1.第二个参数的理解:对于listen的第二个参数参数从未有过正是的定义。一种说法是两个队列的总和的最大值;另一种说法是已完成连接的队列的长度,再乘以一个模糊因子就是总的长度,模糊因子为1.5,不管哪种说法,只是让我们理解的一种手段。2.当listen队列已满的时候,当客户端再发送一个SYN,TCp就会忽略此分节,并且不发送RST。客户TCP将重发SYN,期望不久就能在队列中找到空闲条目。

那么你的listen设置为1,并且多个客户端连接依然没有问题就好理解了。
------解决方案--------------------
第一、阻塞模式下,无accept,connect返回成功
====
这个很正常,listen后,系统内部会接受连接,connect就会成功。但是如果服务器一直不accept,然后多客户端不停的connect,最终会失败。

第二、非阻塞模式下,connect均返回失败
====
非阻塞模式下,connect失败是很正常的,在connect不能立即完成时,就会返回错误,但是连接的过程会继续,这时需要用select来检查连接是否完成(成功或失败)
http://developerweb.net/viewtopic.php?id=3196
[EINPROGRESS]
O_NONBLOCK is set for the file descriptor for the socket and the connection cannot be immediately established; the connection will be established asynchronously.