linux tcp服务器非堵塞,为什么Linux上的非阻塞TCP connect()偶尔会这么慢?

我试图测量我正在编写的TCP服务器的速度,我注意到可能存在测量connect()调用速度的根本问题:如果我以非阻塞方式连接,请连接()操作在几秒钟后变得非常慢.以下是

Python中的示例代码:

#! /usr/bin/python2.4

import errno

import os

import select

import socket

import sys

import time

def NonBlockingConnect(sock,addr):

#time.sleep(0.0001) # Fixes the problem.

while True:

try:

return sock.connect(addr)

except socket.error,e:

if e.args[0] not in (errno.EINPROGRESS,errno.EALREADY):

raise

os.write(2,'^')

if not select.select((),(sock,),(),0.5)[1]:

os.write(2,'P')

def InfiniteClient(addr):

while True:

sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)

sock.setblocking(0)

sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

# sock.connect(addr)

NonBlockingConnect(sock,addr)

sock.close()

os.write(2,'.')

def InfiniteServer(server_socket):

while True:

sock,addr = server_socket.accept()

sock.close()

server_socket = socket.socket(socket.AF_INET,0)

server_socket.setsockopt(socket.SOL_SOCKET,1)

server_socket.bind(('127.0.0.1',45454))

server_socket.listen(128)

if os.fork(): # Parent.

InfiniteServer(server_socket)

else:

addr = server_socket.getsockname()

server_socket.close()

InfiniteClient(addr)

使用NonBlockingConnect,大多数connect()操作都很快,但是每隔几秒就会发生一次connect()操作,至少需要2秒(由输出上的5个连续P字母表示).通过使用sock.connect而不是NonBlockingConnect,所有连接操作似乎都很快.

怎么可能摆脱这些慢连接()?

我正在使用标准PAE内核运行Ubuntu Karmic桌面:

Linux narancs 2.6.31-20-generic-pae #57-Ubuntu SMP Mon Feb 8 10:23:59 UTC 2010 i686 GNU/Linux

奇怪的是strace -f ./conn.py没有延迟.

奇怪的是,如果我取消注释非常快的时间,就没有延迟.sleep.

奇怪的是,我的Ubuntu Hardy系统没有延迟:

所有这些系统都受到影响(运行Ubuntu Karmic,Ubuntu Hardy,Debian Etch):

Linux narancs 2.6.31-20-generic-pae #57-Ubuntu SMP Mon Feb 8 10:23:59 UTC 2010 i686 GNU/Linux

Linux t 2.6.24-grsec #1 SMP Thu Apr 24 14:15:58 CEST 2008 x86_64 GNU/Linux

Linux geekpad 2.6.24-24-generic #1 SMP Fri Sep 18 16:49:39 UTC 2009 i686 GNU/Linux

奇怪的是,以下Debian Lenny系统不受影响:

Linux t 2.6.31.5 #2 SMP Thu Nov 5 15:33:05 CET 2009 i686 GNU/Linux

仅供参考我使用AF_UNIX插槽时没有延迟.

仅供参考我如果在C中实现客户端,我会得到相同的行为:

/* by pts@fazekas.hu at Sun Apr 25 20:47:24 CEST 2010 */

#include

#include

#include

#include

#include

#include

#include

#include

#include

static int work(void) {

fd_set rset;

fd_set wset;

fd_set eset;

socklen_t sl;

struct timeval timeout;

struct sockaddr_in sa;

int sd,i,j;

long l;

sd = socket(AF_INET,SOCK_STREAM,0);

if (sd < 0) {

perror("socket");

return 2;

}

l = fcntl(sd,F_GETFL,0);

if (l < 0) {

perror("fcntl-getfl");

close(sd);

return 2;

}

if (0 != fcntl(sd,F_SETFL,l | O_NONBLOCK)) {

perror("fcntl-setfl");

close(sd);

return 2;

}

memset(&sa,'\0',sizeof(sa));

sa.sin_family = AF_INET;

sa.sin_port = htons(45454);

sa.sin_addr.s_addr = inet_addr("127.0.0.1");

while (0 != connect(sd,(struct sockaddr*)&sa,sizeof sa)) {

if (errno != EAGAIN && errno != EINPROGRESS && errno != EALREADY) {

perror("connect");

close(sd);

return 2;

}

FD_ZERO(&rset);

FD_ZERO(&wset);

FD_ZERO(&eset);

j = 0;

do {

timeout.tv_sec = 0;

timeout.tv_usec = 100 * 1000; /* 0.1 sec */

FD_SET(sd,&wset);

FD_SET(sd,&eset);

i = select(sd + 1,&rset,&wset,&eset,&timeout);

if (i < 0) {

perror("select");

close(sd);

return 2;

}

if (++j == 5) {

(void)write(2,"P",1);

j = 0;

}

} while (i == 0);

sl = sizeof i;

if (0 != getsockopt(sd,SOL_SOCKET,SO_ERROR,&i,&sl)) {

perror("getsockopt");

close(sd);

return 2;

}

if (i != 0) {

if (i == ECONNRESET) {

(void)write(2,"R",1);

close(sd);

return -3;

}

fprintf(stderr,"connect-SO_ERROR: %s\n",strerror(i));

close(sd);

return 2;

}

}

close(sd);

return 0;

}

int main(int argc,char**argv) {

int i;

(void)argc;

(void)argv;

while ((i = work()) <= 0) (void)write(2,".",1);

return i;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值