如何将一个TCP服务器连接到另一个TCP服务器

时间:2019-08-12 21:18:16

标签: c sockets server client

我正在使用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;
}

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

2 个答案:

答案 0 :(得分:2)

TCP连接由其两个端点标识。每一个依次由(IP地址,端口)对标识。因此,您不能在两端具有相同端口的两个IP地址之间同时具有两个不同的连接-如果所有这些属性都相同,则它们是相同的连接。

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

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

如果您想拥有多个并发连接,它们以超出IP地址的某种方式相互关联,那么您需要为其开发一种协议,该协议至少在一端涉及多个端口。如果机器进行双向连接,其中A连接到B,然后B连接到A,那么您将需要在两侧使用不同的端口。使用的端口号可以由协议确定,也可以通过某种方式协商确定,但是您不能随意选择在问题中描述的细节。

答案 1 :(得分:2)

您不能打开可以同时监听和连接的套接字。