linux - 写入关闭的 TCP/IP 连接挂起

标签 linux sockets tcp

我的 TCP/IP 客户端在写入套接字时挂起。即使服务器使用 close()(或使用 shutdown())调用正确关闭已接受的连接,也会发生这种情况。对于这种情况,我一直认为 write 应该返回 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);

编辑: 问题归结为我的编程错误。看来我未能正确开始接受线程。

最佳答案

每个 TCP 连接都有一个接收缓冲区,用于存储已接收但未交付给应用程序的数据。如果在您的服务器中您不执行 read(),那么数据将累积在接收缓冲区中,并且在某一时刻该接收缓冲区变满,导致 TCP 发送 Window=0 消息。

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

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

关于linux - 写入关闭的 TCP/IP 连接挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13487609/

相关文章:

c++ - 在套接字上写多于读

tcp - 视频流协议(protocol)——处理碎片

tcp - 如何使用 Nmap 检索 TCP 和 UDP 端口?

linux - 如何从包含字母数字unix的文件中仅打印数字

编译错误 - sysdeps/i386/elf/start.S 和对 main 的 undefined reference

c# - 在没有垃圾邮件控制台的情况下处理超时的 Socket.ReceiveFrom

java - 并发处理 java.nio.channels.Selector

c - read() 返回正值,但 recvline 中没有任何内容

PHP Cron 作业不执行

C通过命名管道发送分配的字符串 - linux