简体   繁体   English

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

[英]How to connect a TCP server to another TCP server

I'm working with TCP servers. 我正在使用TCP服务器。 Let's say I have a server running with a specific port, but then I want to connect a client to it, I would simply go through the typical procedure of socket, bind, listen, accept for the server and then socket, connect for the client. 假设我有一台运行有特定端口的服务器,但是随后我想将客户端连接到该端口,我将简单地执行套接字的典型过程,依次绑定,监听,接受服务器,然后套接字,为客户端连接。 So let's say our server port is 4000, and our client port 4001. Now, I want to create a new client that will connect to my client on port 4001, but to my limited understanding, I cannot do this as a client. 假设我们的服务器端口是4000,客户端端口是4001。现在,我想创建一个新客户端,该客户端将在端口4001上连接到我的客户端,但是由于我的有限理解,我不能作为客户端来执行此操作。 Port 4001 would have to pertain to a server and not a client (ie it would have to be listening). 端口4001必须属于服务器而不是客户端(即,它必须在侦听)。 The issue arises because I don't think you can use the same port for both the server and client. 出现问题是因为我认为您不能为服务器和客户端使用相同的端口。

I've decided to attempt this through the sample code I've provided below. 我决定尝试通过下面提供的示例代码尝试这种操作。 I call the program on the command line as follows: 我在命令行上按以下方式调用程序:

If this is the first call of the server, then I simply call the program without any arguments and it will automatically run on port 3000. ie ./serverprogram 如果这是服务器的第一次调用,那么我只需调用不带任何参数的程序,它将自动在端口3000上运行。即./serverprogram

If I would like to connect a client on port 3001 to our server on port 3000. Then I would call the command line with two arguments, the first being 3001 and the second being 3000. ie ./serverprogram 3001 3000 如果我想将端口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;
}

Upon running the second instance of the program I receive the error "bind: Invalid argument". 运行程序的第二个实例时,我收到错误“ bind:Invalid arguments”。 I am assuming that this is due to the fact that the port is already in use. 我假设这是由于该端口已在使用中。 Is there any way to bypass this, or is there any way to connect a server to a client, and allow the client to also act as a server using the same port 是否有任何方法可以绕过此操作,或者有任何方法将服务器连接到客户端,并允许客户端也使用同一端口充当服务器

A TCP connection is identified by its two endpoints. TCP连接由其两个端点标识。 Each of those, in turn, is identified by an (IP address, port) pair. 每一个依次由(IP地址,端口)对标识。 Therefore, you cannot simultaneously have two distinct connections between the same two IP addresses with the same ports on each end -- if all of those properties are the same, then they are the same connection. 因此,您不能在两端具有相同端口的相同两个IP地址之间同时具有两个不同的连接-如果所有这些属性都相同,则它们是相同的连接。

From the perspective of system interfaces, you cannot create that situation because the system will not allow you to bind an address / port pair that is already in use to any socket (a stronger constraint than is strictly required). 从系统接口的角度来看,您无法创建这种情况,因为系统不允许您将已经使用的地址/端口对绑定到任何套接字(比严格要求更严格的约束)。 This means that one machine cannot use the same port simultaneously for both a client socket and a server socket, even for different remote endpoints. 这意味着一台计算机不能同时将相同的端口用于客户端套接字和服务器套接字,即使对于不同的远程端点也是如此。

You can , however, have any number of simultaneous TCP connections that each differ from all the others in at least one of those parameters. 但是,您可以具有任意数量的并发TCP连接,这些连接中至少有一个参数与其他所有TCP连接不同。 In particular, you can have any number of connections between the same two machines, with the same port on one side, and different ports on the other. 特别是,您可以在同一台两台计算机之间建立任意数量的连接,一侧具有相同的端口,而另一侧具有不同的端口。 This is extremely common, in fact, as web browsers often open multiple simultaneous connections to a web server to download multiple resources concurrently. 实际上,这是非常普遍的,因为Web浏览器经常打开与Web服务器的多个同时连接以同时下载多个资源。 All of those connections have the same server address, server port, and client address, but different client port. 所有这些连接具有相同的服务器地址,服务器端口和客户端地址,但客户端端口不同。

If you want to have multiple simultaneous connections that are associated with one another in some way that goes beyond IP addresses, then you'll need to develop a protocol for it that involves multiple ports at at least one end. 如果您希望拥有多个同时连接,并且这些连接以超出IP地址的某种方式相互关联,那么您需要为其开发一种协议,该协议至少在一端涉及多个端口。 If the machines make reciprocal connections, with A connecting to B and then B connecting, separately, to A, then you'll need different ports on both sides. 如果机器进行双向连接,其中A连接到B,然后B连接到A,那么您将需要在两侧使用不同的端口。 The port numbers to use might be fixed by the protocol or negotiated in some way, at your discretion, but the specifics described in the question are not an option. 您可以根据自己的判断,使用协议确定的端口号或通过某种方式协商使用的端口号,但问题中描述的具体内容不是可选的。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM