写入已关闭的TCP / IP连接会挂起

时间:2012-11-21 06:30:30

标签: linux sockets tcp

我的TCP / IP客户端在写入套接字时挂起。即使服务器正确关闭了close()(或shutdown())调用的已接受连接,也会发生这种情况。在这种情况下,我一直认为写入应该返回ECONNRESET错误。

如何防止同步输出中的挂起?或者更确切地说,我做错了什么,以便write()报告错误?

我应该使用send()代替write()还是可以互换?

我正在使用两个线程在单独的应用程序中测试网络。 主线程启动服务器线程,接受连接并立即关闭它。然后,主线程通过连接到侦听端口来模仿客户端行为。

主线程代码:

sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port);
int s = socket(AF_INET, SOCK_STREAM, 0);
if (bind(s, (sockaddr*)(&serv_addr),  sizeof(serv_addr)) < 0) {
    close(s);
    throw runtime_error(strerror(errno));
}
listen(s,1);
start_thread(s); // posix thread accepting a connection on s is started here
//Code below imitates  TCP/IP client
struct hostent *hp;
struct sockaddr_in addr;
if((hp = gethostbyname(host.c_str())) == NULL){
    throw HErrno();
}
bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
int _socket = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (_socket < 0) {
    throw Errno();
}
assert(ENOTCONN==107);
assert(_socket>=0);
if(::connect(_socket, (const struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == -1){
    throw Errno();
}

while(true) {
  const char a[] = "pattern";
  if (write( _socket, a, 7)<0) // Writes 30000 times, then hangs
     break;
}

服务器线程代码:

int connection = accept(s);
close(connection);

修改 问题减少了我的编程错误。好像我没能开始正确接受线程。

2 个答案:

答案 0 :(得分:1)

每个TCP连接都有一个接收缓冲区,用于存储接收但未传送到应用程序的数据。如果在您的服务器中没有执行read(),则数据会在接收缓冲区中累积,并且此接收缓冲区在某一点变满,导致TCP发送Window = 0消息。

您的服务器线程代码应如下所示:

char a[10];
int connection = accept(s);
while(true)
    if (read( connection , a, 7)<=0)
        break;
close(connection);

答案 1 :(得分:0)

您是否为SIGPIPE设置了处理程序,而不是将其设置为SIG_IGN