2013-10-28 83 views
0

我一直工作在一些服务器客户端代码最近,我发现了一个非常混乱的疑难问题有server监听端口,并设置积压= 2,和我的客户创建5个线程connect的Mac OSX 10.9监听要完成的工作无法正常

man,我注意到

The backlog parameter defines the maximum length for the queue of pending 
connections. If a connection request arrives with the queue full, the 
client may receive an error with an indication of ECONNREFUSED. Alterna- 
tively, if the underlying protocol supports retransmission, the request 
may be ignored so that retries may succeed. 

这意味着我的客户端连接将失败重试以后。

但是当我的客户端运行时,它只是得到一个SIGPIPE信号而失败。

所以我跑sudo tcpdump -ilo0 port 10000,并得到结果:

summertekiMacBook-PRO:选择夏天$ sudo的tcpdump的-ilo0端口10000

的tcpdump:详细的输出抑制,使用-v或-vV全协议解码侦听lo0,链路类型NULL(BSD环回),捕获大小65535字节

10:29:16.396240 IP localhost.56347> localhost.ndmp:Flags [S],seq 3366561899,win 65535,options [mss 16344,nop,wscale 4,nop,nop,TS val 396158772 ecr 0,sackOK,eol],长度0

10:29:16.396241 IP localhost.56349> localhost.ndmp:Flags [S],seq 902832276,win 65535,options [mss 16344,nop,wscale 4,nop,nop,TS val 396158772 ecr 0,sackOK ,eol],长度0

10:29:16.396242 IP localhost.56351> localhost.ndmp:Flags [S],seq 1956535575,win 65535,options [mss 16344,nop,wscale 4,nop,nop,TS VAL 396158772 ECR 0,sackOK,EOL],长度为0

10:29:16.396244 IP localhost.56348> localhost.ndmp:旗[S],SEQ 2161003109,赢得65535,期权[MSS 16344,NOP,wscale 4 ,nop,nop,TS val 396158772 ecr 0,sackOK,eol],长度0

10:29:16.396246 IP localhost.56350> localhost.ndmp:Flags [S],seq 1318035540,win 65535,options [mss 16344,nop,wscale 4,nop,nop,TS val 396158772 ecr 0,sackOK,eol] ,长度0

10:29:16.396296 IP localhost.ndmp> localhost.56347:Flags [S.],seq 2871094527,ack 3366561900,win 65535,options [mss 16344,nop,wscale 4,nop,nop, TS VAL 396158772 ECR 396158772,sackOK,EOL],长度为0

10:29:16.396307 IP localhost.ndmp> localhost.56351:旗[S.],SEQ 3931313020,ACK 1956535576,赢得65535,期权[MSS 16344 ,nop,wscale 4,nop,nop,TS val 396158772 ecr 396158772,sackOK,eol],长度0

10:29:16.396332 IP localhost.ndmp> localhost .56349:标记[S.],seq 3467781056,ack 902832277,获胜65535,选项[mss 16344,nop,wscale 4,nop,nop,TS val 396158772 ecr 396158772,sackOK,eol],长度0

10 :29:16.396349 IP localhost.ndmp> localhost.56348:Flags [S.],seq 2666080832,ack 2161003110,win 65535,options [mss 16344,nop,wscale 4,nop,nop,TS val 396158772 ecr 396158772,sackOK, eol],长度0

10:29:16.396366 IP localhost.ndmp> localhost。56350:Flags [S.],seq 2467582351,ack 1318035541,win 65535,options [mss 16344,nop,wscale 4,nop,nop,TS val 396158772 ecr 396158772,sackOK,eol],长度0

10: 29:16.396375 IP localhost.56347> localhost.ndmp:旗,ACK 1,赢得9186,选项[NOP,NOP,TS VAL 396158772 ECR 396158772],长度为0

10。]:29:16.396381 IP本地主机。 56351> localhost.ndmp:标志[。],ack 1,win 9186,选项[nop,nop,TS val 396158772 ecr 396158772],长度0

10:29:16.396386 IP localhost.56349> localhost.ndmp: Flags [。],ack 1,win 9186,选项[nop,nop,TS val 396158772 ecr 396158772],长度0

10:29:16.396391 IP localhost.56348> localhost.ndmp:[]旗,ACK 1,赢得9186,选项[NOP,NOP,TS VAL 396158772 ECR 396158772],长度为0

10时29分:16.396398 IP localhost.56350> localhost.ndmp:Flags [。],ack 1,win 9186,options [nop,nop,TS val 396158772 ecr 396158772],长度0

10:29:16.396408 IP localhost.ndmp > localhost.56347:旗[R],SEQ 2871094528,赢0,长度为0

10:29:16.396413 IP localhost.ndmp> localhost.56351:旗[R],SEQ 3931313021,赢0,长度为0

10:29:16.396419 IP localhost.56347> localhost.ndmp:标记[P.],seq 1:1001,ack 1,win 9186,选项[nop,nop,TS val 396158772 ecr 396158772],长度1000

10:29:16.396424 IP localhost.56351> localhost.ndmp:标志[P.],seq 1:1001,ack 1,win 9186,选项[nop,nop,TS val 396158772 ecr 396158772],长度1000

10:29:16.396429 IP localhost.ndmp> localhost.56349:Flags [。],ack 1,win 9186,options [nop,nop,TS val 396158772 ecr 396158772],长度0 10:29:16.396435 IP本地主机。 ndmp> localhost.56348:Flags [R],seq 2666080833,win 0,length 0

10:29:16.396441 IP localhost.nd mp> localhost.56350:Flags [。],ack 1,win 9186,options [nop,nop,TS val 396158772 ecr 396158772],长度0

10:29:16.396454 IP localhost.ndmp> localhost.56347:标志[R],SEQ 2871094528,赢0,长度为0

10:29:16.396460 IP localhost.ndmp> localhost.56351:旗[R],SEQ 3931313021,赢0,长度为0

来自unix网络编程,connect()将启动3次握手例程,并返回服务器发送时syn & & ack

tcpdump输出,最高10行告诉记者,服务器回复SYN & SCK虽然积压为2之后,客户端发送末次ACK和服务器返回RST

在我看来,连接返回值!= -1意味着连接建立&客户端能够发送数据。但是上面的日志显示表明它不能以这种方式工作。

那么谁能告诉我哪个是正确

回答

0

当您尝试在损坏/关闭的管道上发送数据时,会收到SIGPIPE信号。 根据你的tcpdump的数据,并为你解释:

  • 全部5 TCP连接是由5个不同的客户端端口(56347-56351)正确建立(与3次握手)。
  • 然后,服务器从端口47和51的连接中发送重置。这会中断管道。
  • 几乎与此同时数据正在从端口47和51(在客户端)发送([P],推送)到服务器。可能这个数据已经在内核定义的时候就准备好发送到套接字发送缓冲区了。稍后,服务器再次用Reset [R]响应,但这不会改变任何事情。
  • 其实你tcpdump中的最后4行不影响这个解释。

连接实际上在您的客户端程序中返回OK。我敢肯定,因为所有连接均已建立完成,并且3次握手完成。问题是,之后你立即尝试发送数据,我敢打赌,你试图在每个套接字中多次发送数据。我假设每个线程处理一个套接字。线程尝试在端口为56347或56351的套接字上发送数据的第二个或第三个(或更多)时间,管道因为已从服务器接收到RESET而中断,操作系统将向该进程发送信号SIGPIPE。

收听积压似乎在您的服务器上正常工作。看来3个连接正确处理,只有2个被拒绝。可能服务器处理第一个连接的速度足够快,以便为未来2个待办事项留下空间。后两项无法完成,因为积压太小(2)。

+0

在我的选择中,backlog表示队列的大小(包括服务器**回复ack **和连接**服务器接收syn **的连接)在上面的示例中,服务器一次获得5个连接,但队列为只有2,所以其余3应该是**忽略**或**获得ECONNREFUSED **,但它不是那样。 < – summer

1

最后,花时间搜索一下后,我已经解释了上面的行为。

我检查linux manual它表明:

在TCP套接字积压参数的行为在Linux 2.2改变。现在,它指定队列长度为完全建立插座等待被接受的代替不全连接请求的数量。不完整套接字队列的最大长度可以使用/ proc/sys/net/ipv4/tcp_max_syn_backlog来设置。当启用syncookies时,没有逻辑最大长度,这个设置被忽略。有关更多信息,请参阅tcp(7)。

而且也,在freebsd manualosx's manual透露任何细节,但由于两个操作系统都是基于BSD ^^):

注意,之前的FreeBSD 4 。5引入syncache中, 积压参数也决定了不完全连接 队列,这在完成TCP的3路握手 的进程所持有的TCP套接字的长度。这些不完整的连接现在是完全持有syncache,这是不受影响按队列长度。充值积压值 帮助处理拒绝服务攻击不再是必要的。

总之,好像原因为积压行为的变化,以保护SYN Flood攻击服务。