【问题标题】:How to connect a TCP server to another TCP server如何将一个 TCP 服务器连接到另一个 TCP 服务器
【发布时间】:2019-12-19 10:58:25
【问题描述】:

我正在使用 TCP 服务器。假设我有一个使用特定端口运行的服务器,但是我想将一个客户端连接到它,我将简单地通过套接字、绑定、侦听、接受服务器的典型过程,然后是套接字,连接客户端.所以假设我们的服务器端口是 4000,我们的客户端端口是 4001。现在,我想创建一个新客户端,它将在端口 4001 上连接到我的客户端,但据我所知,作为客户端,我不能这样做。端口 4001 必须属于服务器而不是客户端(即它必须正在侦听)。出现问题是因为我认为您不能为服务器和客户端使用相同的端口。

我决定通过下面提供的示例代码来尝试一下。我在命令行中调用程序如下:

如果这是服务器的第一次调用,那么我只需调用不带任何参数的程序,它将自动在端口 3000 上运行。即 ./serverprogram

如果我想将端口 3001 上的客户端连接到端口 3000 上的服务器。然后我会使用两个参数调用命令行,第一个是 3001,第二个是 3000。即 ./serverprogram 3001 3000

#define PORT 3000

int main (int argc, char * argv[]){
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    int my_port = (argc == 3) ? atoi(argv[1]) : PORT;

    if (argc > 2){
        struct sockaddr_in c_addr;
        c_addr.sin_family = AF_INET;
        memset(&c_addr.sin_zero, 0, 8);
        c_addr.sin_port = htons(atoi(argv[2]));

        struct addrinfo *result = NULL;
        getaddrinfo("AcaciaLinux", NULL, NULL, &result);
        struct sockaddr_in *x = (struct sockaddr_in*) result->ai_addr;
        c_addr.sin_addr = x->sin_addr;
        freeaddrinfo(result);

        if(connect(sfd, (struct sockaddr *) &c_addr, sizeof(struct sockaddr_in)) == -1){
            perror("connect");
            exit(1);
        }
        printf("We have connected to a server.");
    }

    if (sfd == -1){
        perror("socket");
        exit(1);
    }

    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(my_port);
    saddr.sin_addr.s_addr = INADDR_ANY;
    memset(&(saddr.sin_zero), 0, 8);

    if(bind(sfd, (struct sockaddr*) &saddr, sizeof(struct sockaddr_in)) == -1){
        perror("bind");
        close(sfd);
        exit(1);
    }

    if (listen(sfd, 5) < 0){
        perror("listen");
        exit(1);
    }


    struct sockaddr_in caddr;
    saddr.sin_family = AF_INET;

    int cfd;

    unsigned int c_len = sizeof(struct sockaddr_in);

    if ((cfd = accept(sfd, (struct sockaddr*) &caddr, &c_len)) == -1){
        perror("accept");
        exit(1);
    }

    printf("Alas, we have finally connected to a client.");

    return 0;
}

在运行程序的第二个实例时,我收到错误“绑定:无效参数”。我假设这是由于该端口已在使用中。有没有办法绕过这个,或者有什么办法可以将服务器连接到客户端,并允许客户端也可以使用相同的端口充当服务器

【问题讨论】:

  • 我想你是说你想为连接指定客户端端口。在connect()ing 之前bind()ing 套接字应该是可能的(一次一个连接),但是为什么这对你很重要?
  • 为什么?客户端端口有什么关系?
  • 对不起,但我仍然不明白为什么控制客户端端口号可以让你做一些你不能做的事情。
  • @OsamaHafez: "我希望服务器和客户端都引用相同的端口号,以便我连接的服务器可以通过相同的端口引用我的程序的运行实例正如客户所做的那样。” - 但为什么呢?对我来说,这看起来像是一个虚构的问题,或者像 XY problem,即您为某些未知问题 X 提出了一个“解决方案”Y,但不幸的是 Y 不起作用。如果不知道 X,想要 Y 是没有意义的,而知道 X 可能会有更好的解决方案。
  • 服务器不需要使用端口引用客户端。它只是发送到 TCP 连接,然后发送到相应的客户端。您需要第二个独立连接吗?查看 FTP 使用控制和数据连接的方式。

标签: c sockets server client


【解决方案1】:

你不能打开一个既能监听又能连接的套接字。

【讨论】:

    【解决方案2】:

    一个 TCP 连接由它的两个端点来标识。反过来,其中的每一个都由(IP 地址,端口)对标识。因此,您不能同时在两端具有相同端口的相同两个 IP 地址之间建立两个不同的连接——如果所有这些属性都相同,那么它们就是相同的连接。

    从系统接口的角度来看,您无法创建这种情况,因为系统不允许您将已在使用的地址/端口对绑定到任何套接字(比严格要求的约束更强)。这意味着一台机器不能同时为客户端套接字和服务器套接字使用相同的端口,即使对于不同的远程端点也是如此。

    但是,您可以拥有任意数量的同时 TCP 连接,每个连接至少在其中一个参数上与所有其他连接不同。特别是,您可以在相同的两台机器之间建立任意数量的连接,一侧使用相同端口,另一侧使用不同端口。事实上,这非常常见,因为 Web 浏览器经常同时打开多个到 Web 服务器的连接以同时下载多个资源。所有这些连接都具有相同的服务器地址、服务器端口和客户端地址,但客户端端口不同。

    如果您希望有多个同时以某种方式相互关联的连接超出 IP 地址,那么您需要为其开发一种协议,该协议至少在一端涉及多个端口。如果机器进行相互连接,A 连接到 B,然后 B 分别连接到 A,那么两边都需要不同的端口。要使用的端口号可能由协议固定或以某种方式协商,由您自行决定,但问题中描述的细节不是一个选项。

    【讨论】:

    • "系统将不允许您将已在使用的地址/端口对绑定到任何套接字" - 如果您启用 SO_REUSEADDR/@987654322,则可以@ 套接字上的选项。
    • 是的,@RemyLebeau,在某种程度上,但即使这样也不允许将用于活动侦听套接字的本地地址绑定到另一个套接字。
    • 它适用于多个侦听器套接字,但可能不适用于连接器套接字。从未尝试过使用连接器,仅适用于听众。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 2016-08-26
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    • 2017-01-27
    • 2019-03-15
    相关资源
    最近更新 更多