最近我一直在编写一些服务器客户机代码,我发现了一个非常令人困惑的问题,我在端口上安装了一个server侦听程序,并设置了backlog = 2,并且我的客户端创建了5线程 to connect。
在man,我注意到
backlog参数定义挂起连接队列的最大长度。如果连接请求到达时队列已满,则客户端可能会收到带有ECONNREFUSED指示的错误。另外,如果底层协议支持重传,则请求可能被忽略,以便重试可能成功。
这意味着我的客户端连接会失败或者稍后再试。
但是当我的客户端运行时,它只是得到一个SIGPIPE信号,但失败了。
所以我运行sudo tcpdump -ilo0 port 10000并得到结果:
summertekiMacBook:选择夏季$ sudo -ilo0端口10000 tcpdump:详细的输出被抑制,使用-v或-vv进行完整的协议解码,侦听lo0,链接类型为NULL (BSD回环),捕获大小为65535字节。 10:29:16.396240 IP localhost.56347 > localhost.ndmp:标志S,seq 3366561899,win 65535,选项mss 16344,nop,wscale 4,nop,nop,TS val 396158772 ecr 0,sackOK,eol,长度0 10:29:16.396241 IP localhost.56349 > localhost.ndmp:标志S,seq 902832276,win 65535,选项mss 16344,nop,wscale 4,nop,TS val 396158772 ecr 0,sackOK,eol,长度0 10:29:16.396242 IP localhost.56351 > localhost.ndmp:标志S,seq 1956535575,win 65535,选项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,win 65535,选项mss 16344,nop,wscale 4,nop,TS val 396158772 ecr 0,sackOK,eol,长度0 10:29:16.396246 IP localhost.56350 > localhost.ndmp:标志S,seq 1318035540,win 65535,选项mss 16344,nop,wscale 4,nop,nop,TS val 396158772 ecr 0,sackOK,eol,长度0 10:29:16.396296 IP localhost.ndmp > localhost.56347:旗标S,seq 2871094527,ack 3366561900,win 65535,选项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,win 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,win 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:旗标S,seq 2666080832,ack 2161003110,win 65535,选项mss 16344,nop,wscale 4,nop,nop,TS val 396158772 ecr 396158772,sackOK,eol,长度0 10:29:16.396366 IP localhost.ndmp > localhost.56350:旗标S,seq 2467582351,ack 1318035541,win 65535,选项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,win 9186,选项nop,nop,TS val 396158772 ecr 396158772,长度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:旗标,ack 1,win 9186,选项nop,nop,TS val 396158772 ecr 396158772,长度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,seq 2871094528,win 0,长度0 10:29:16.396413 IP localhost.ndmp > localhost.56351:标志R,seq 3931313021,win 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:旗标,ack 1,win 9186,选项nop,nop,TS val 396158772 ecr 396158772,长度0 10:29:16.396435 IP localhost.ndmp > localhost.56348:标志R,seq 2666080833,win 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,seq 2871094528,win 0,长度0 10:29:16.396460 IP localhost.ndmp > localhost.56351:标志R,seq 3931313021,win 0,长度0
从unix网络编程,connect()将启动3次握手例程,并在服务器发送syn & ack时返回。
从tcpdump输出中,前10行告诉服务器回复syn & sck,尽管backlog是2,但后来,客户端发送最后一次攻击和服务器返回rst。
在我看来,连接返回值!= -1意味着建立了连接&客户机能够发送数据。但是上面的日志显示它不是那样工作的。
所以有人能告诉我哪个是正确的吗
发布于 2013-10-31 16:05:31
最后,在花时间搜索之后,我得到了上述行为显示的解释。
我检查了linux手册,它显示:
备注 在Linux2.2中,TCP套接字上的待定参数的行为发生了变化。现在它指定了队列长度,用于完全建立的等待被接受的套接字,而不是--不完全的连接请求的数量。不完全套接字的最大队列长度可以使用/proc/sys/net/ipv4 4/tcp_max_syn_backlog设置。启用syncookie时,不存在逻辑最大长度,因此将忽略此设置。有关更多信息,请参见tcp(7)。
而且,在freebsd手册中(osx手册没有给出任何细节,但是因为两个os都基于bsd ^.^):
注意,在 4.5之前,以及同步缓存的引入之前,backlog参数还决定了不完全连接队列的长度,该队列在完成TCP的3路握手过程中持有TCP套接字。这些不完整的连接现在在syncache中完全由保存,这是按队列长度计算的未受影响的。不再需要膨胀的待办事项处理值来帮助处理拒绝服务攻击。
总之,对于积压行为的改变,原因似乎是为了保护服务不受系统洪水攻击的影响。
发布于 2013-10-28 19:41:01
当您试图在断开/关闭的管道上发送数据时,您会收到SIGPIPE信号。根据您的tcpdump数据,正如您所解释的:
连接实际上返回OK在您的客户端程序。我确定,因为所有的连接都建立好了,三人握手完成了。问题是,在此之后,您将立即尝试发送数据,我敢打赌,您将尝试在每个套接字中多次发送数据。我假设每个线程处理一个套接字。第二次或第三次(或更多)时间,线程试图用端口56347或56351在套接字上发送数据,由于已经从服务器接收到重置,管道中断,操作系统将向进程发送信号SIGPIPE。
听一听,待办事项似乎在您的服务器上正常工作。似乎有3个连接被正确处理,只有2个被拒绝。可能服务器处理第一个连接的速度足够快,足以为待办事项中的下一个2留下位置。最后两个无法完成,因为待办事项太小(2)。
https://stackoverflow.com/questions/19626527
复制相似问题