如何确定网络堆栈何时可以再次打开到同一主机/端口的套接字?

时间:2018-01-04 18:21:10

标签: c++ c sockets posix berkeley-sockets

我有以下C程序,其主函数runTCPConnectivityCheck打开一个TCP套接字,向它发送一串字节并关闭它:

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

static int runTCPConnectivityCheck(const int port)
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0)
    {
        printf("socket failed\n");
        return 1;
    }

    int reuseAddrTrue = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseAddrTrue, sizeof(reuseAddrTrue)) != 0)
    {
        printf("setsockopt failed\n");
        return 1;
    }

    struct sockaddr_in serv_addr = { 0 };
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);

    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) != 1)
    {
        printf("inet_pton failed\n");
        return 1;
    }

    if (connect(fd, (struct sockaddr*)(&serv_addr), sizeof(serv_addr)) != 0)
    {
        printf("connect failed\n");
        return 1;
    }

    const char* message = "hello";
    const size_t messageLength = strlen(message);
    if (send(fd, message, messageLength, 0) != messageLength)
    {
        printf("send failed\n");
        return 1;
    }

    shutdown(fd, SHUT_RDWR);
    close(fd);

    return 0;
}

int main()
{
    for (int i = 0; i < 10; ++i)
    {
        printf("%s\n", runTCPConnectivityCheck(5555) == 0 ? "success" : "failure");
        //sleep(1);
    }
}

如果我尝试重复测试同一个端口,第一次调用runTCPConnectivityCheck的工作正常,但所有后续调用在调用connect时失败。如果我将调用添加到sleep,那么它也可以。据推测,1秒的延迟使网络堆栈有足够的时间来清理套接字,这样我就可以再次连接到同一个端口。

首先:我是否正确关闭了插座?其次:如果我正确关闭它,那么确定何时网络堆栈已准备好再次连接到同一主机和端口(而不是我当前正在使用的跛脚sleep)的标准方法是什么? / p>

更新

更多详细信息:connect失败,错误代码为61或ECONNREFUSEDstrerror正在返回“拒绝连接”。

在这种情况下,服务器是在与测试程序相同的机器上循环运行的netstat / nc命令:

#!/bin/bash
while true; do
  nc -l 5555
done

程序现在是C,真实。

1 个答案:

答案 0 :(得分:0)

普遍的共识是客户端代码没有什么特别的错误。事实证明我的测试服务器无法跟上我的客户端:

#!/bin/bash
while true; do
  nc -l 5555
done

我在Python中编写了一个分叉服务器,它可以毫无困难地为所有客户端连接提供服务。