Mac OSX 10.9侦听囤积工作不正常



我最近一直在处理一些服务器客户端代码,发现了一个非常令人困惑的问题。我有一个server侦听端口,并将backlog设置为2,我的客户端connect创建5个线程

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:选择summer$sudo tcpdump-ilo0端口10000

tcpdump:抑制详细输出,在lo0上使用-v或-vv进行全协议解码侦听,链接类型为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],length 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],length 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],length 0

10:29:16.396244 IP localhost.56348>localhost.ndmp:Flags[S],seq 2161003109,win 65535,options[mss 16344,nop,wscale 4,nop、nop,TS val 396158772 ecr 0,sackOK,eol],length 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],length 0

10:29:16.396296 IP localhost.ndmp>localhost.56347:标志[S.],序列号2871094527,ack 3366561900,win 65535,选项[mss 16344,nop,wscale 4,nop

10:29:16.396307 IP localhost.ndmp>localhost.56351:标志[S.],序列号3931313020,ack 1956535576,win 65535,选项[mss 16344,nop,wscale 4,nop

10:29:16.396332 IP localhost.ndmp>localhost.56349:标志[S.],序列号3467781056,ack 902832277,win 65535,选项[mss 16344,nop,wscale 4,nop

10:29:16.396349 IP localhost.ndmp>localhost.56348:标志[S.],序列号2666080832,ack 2161003110,win 65535,选项[mss 16344,nop,wscale 4,nop

10:29:16.396366 IP localhost.ndmp>localhost.56350:标志[S.],序列号2467582351,ack 1318035541,win 65535,选项[mss 16344,nop,wscale 4,nop

10:29:16.396375 IP localhost.56347>localhost.ndmp:Flags[.],ack 1,win 9186,options[nop,nop,TS val 396158772 ecr 396158772],length 0

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

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

10:29:16.396391 IP localhost.56348>localhost.ndmp:Flags[.],ack 1,win 9186,options[nop,nop,TS val 396158772 ecr 396158772],length 0

10:29:16.396398 IP localhost.56350>localhost.ndmp:标志[.],ack 1,win 9186,选项[nop,nop,TS val 396158772 ecr 396158772],长度0

10:29:16.396408 IP localhost.ndmp>localhost.56347:标志[R],序列号2871094528,获胜0,长度0

10:29:16.396413 IP localhost.ndmp>localhost.56351:标志[R],序列号3931313021,获胜0,长度0

10:29:16.396419 IP localhost.56347>localhost.ndmp:Flags[p.],seq 1:1001,ack 1,win 9186,options[nop,nop,TS val 396158772 ecr 396158772],length 1000

10:29:16.396424 IP localhost.56351>localhost.ndmp:Flags[p.],seq 1:1001,ack 1,win 9186,options[nop,nop,TS val 396158772 ecr 396158772],length 1000

10:29:16.396429 IP localhost.ndmp>localhost.56349:标志[.],ack 1,win 9186,选项[nop,nop,TS val 396158772 ecr 396158772],长度010:29:16.396435 IP localhost.ndmp>localhost.56348:标志[R],序列号2666080833,获胜0,长度0

10:29:16.396441 IP localhost.ndmp>localhost.56350:标志[.],ack 1,win 9186,选项[nop,nop,TS val 396158772 ecr 396158772],长度0

10:29:16.396454 IP localhost.ndmp>localhost.56347:标志[R],序列号2871094528,获胜0,长度0

10:29:16.396460 IP localhost.ndmp>localhost.56351:标志[R],序列号3931313021,获胜0,长度0

unix网络编程开始,connect()将启动3次握手例程,并在服务器发送syn&ack

tcpdump输出,前10行告诉服务器回复syn&sck,尽管backback是2。稍后,客户端发送上次ack,服务器返回rst。

在我看来,将回报与价值联系起来!=-1表示建立连接&客户端能够发送数据。但上面的日志显示,它并不是这样工作的。

有人能告诉我哪个是正确的吗?

最后,在花时间搜索之后,我得到了上面显示的行为的解释。

我查看了linux手册,它显示:

票据

在Linux 2.2中,TCP套接字上backlog参数的行为发生了变化。现在,它为完全建立的等待接受的套接字指定队列长度,而不是不完整的连接请求数。可以使用/proc/sys/net/ipv4/tcp_max_sync_backlog设置不完整套接字的队列的最大长度。启用syncookies时,没有逻辑最大长度,此设置将被忽略。有关更多信息,请参阅tcp(7)。

此外,在freebsd手册中(osx的手册没有给出任何细节,但由于两个操作系统都基于bsd^.^):

请注意,在FreeBSD 4.5之前引入syncachebacklog参数还确定了不完整连接的长度队列,在完成TCP的3路过程中容纳TCP套接字握手。这些不完整的连接现在被完全保持在同步缓存,它不受队列长度的影响。膨胀的囤积值不再需要帮助处理拒绝服务攻击。

总之,更改囤积行为的原因似乎是为了保护服务免受syn洪水攻击

当您尝试在断开/闭合的管道上发送数据时,会收到SIGPIPE信号。根据您的tcpdump数据,正如您所解释的:

  • 从5个不同的客户端端口(56347-56351)正确建立了所有5个TCP连接(使用3向握手)
  • 然后,服务器在来自端口47和51的连接中发送Reset。这打破了管道
  • 几乎同时,数据从端口47和51(在客户端中)发送([P],推送)到服务器。这些数据可能已经在套接字发送缓冲区中,准备在内核决定时发送。稍后,服务器再次响应Reset[R],但这不会改变任何内容
  • 实际上,tcpdump中的最后4行并不影响这个解释

connect在您的客户端程序中实际返回OK。我确信,因为所有的连接都建立得很好,完成了3次握手。问题是,在那之后,你会立即尝试发送数据,我敢打赌,你会尝试在每个套接字中多次发送数据。我假设每个线程处理一个套接字。线程第二次或第三次(或更多次)尝试在具有端口56347或56351的套接字上发送数据时,由于已经从服务器接收到RESET,管道断开,操作系统将向进程发送信号SIGPIPE。

listenbacklog在您的服务器中似乎可以正常工作。似乎有3个连接被正确处理,只有2个被拒绝。可能服务器处理第一个连接的速度足够快,可以在backlog中为下一个2留出位置。最后两个没能成功,因为积压的工作太少了(2)。

相关内容

  • 没有找到相关文章

最新更新