0

这些天我一直在研究网络编程,我写了两个简单的例程来检查我是否做对了。所以我在桌面上构建了服务器并启动它,然后我在笔记本电脑上构建了客户端并运行它,一切都按预期进行。当我第二次尝试运行它们时,服务器一直在循环,两秒钟后客户端给出“连接错误!”。如果我在十五分钟后再试一次,它会起作用,但我必须再次等待。我哪里错了?计算机都连接到我的 LAN,79.13.199.165 是我的调制解调器/路由器的 IP,它将端口 53124 上的每个传入连接转发到桌面。在同一台 PC 上同时运行服务器和客户端时不会出现此问题。

服务器.c

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

int main () {
    struct sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_port = htons(53124);
    sa.sin_addr.s_addr = htonl(INADDR_ANY);
    memset(sa.sin_zero, '\0', sizeof(sa.sin_zero));

    int mysocket = socket(PF_INET, SOCK_STREAM, 0);
    bind(mysocket, (struct sockaddr*)&sa, sizeof(sa));
    listen(mysocket, 5);

    int inc;
    struct sockaddr_in inc_addr;
    socklen_t inc_addr_size = sizeof(inc_addr);
    inc = accept(mysocket, (struct sockaddr*)&inc_addr, &inc_addr_size);
    if (inc != -1) {
            printf("accepting client\n");
    }
    send(inc, "ciao", sizeof("ciao"), 0);
    close(inc);

    return 0;
}

客户端.c

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

int main () {

    struct sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_port = htons(53124);
    sa.sin_addr.s_addr = inet_addr("79.13.199.165");
    memset(sa.sin_zero, '\0', sizeof(sa.sin_zero));

   int mysocket = socket(PF_INET, SOCK_STREAM, 0);
   if (mysocket == -1) {
       printf("Could not create socket!\n");
    }
   if (connect(mysocket, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
       printf("Error connecting!\n");
    }
   char message[5];
   memset(message, '\0', sizeof(message));
   recv(mysocket, message, 5, 0);
   printf("%s\n", message);

   return 0;
}
4

1 回答 1

4

当服务器关闭套接字时,几个 ACK​​ 数据包会通过连接来回发送。无法判断最后一个 ACK​​ 是否成功传递,因此连接会进入 TIME_WAIT 状态一段时间。这基本上让 TCP 堆栈有时间等待任何丢失的数据包并将它们丢弃。

通过使用setsockopt()设置SO_REUSEADDR可以忽略这一点并立即重用套接字。后续连接可能会获得他们不应该获得的数据,但对于您的小型测试应用程序来说,这应该不是问题。

编辑

顺便说一句,您可能对此感到困惑的一个原因是您没有对 socket() bind() 或 listen() 进行任何错误检查。bind() 调用肯定会返回错误并在 Linux 上设置 errno, EINVAL。

于 2012-04-16T13:41:39.987 回答