如何将一个 TCP 服务器连接到另一个 TCP 服务器
How to connect a TCP server to another TCP server
我正在使用 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: Invalid argument"。我假设这是由于该端口已被使用。有什么方法可以绕过这个,或者有什么方法可以将服务器连接到客户端,并允许客户端也使用相同的端口充当服务器
TCP 连接由其两个端点标识。反过来,每一个都由一对(IP 地址、端口)标识。因此,您不能同时在两端具有相同端口的相同两个 IP 地址之间建立两个不同的连接——如果所有这些属性都相同,那么它们就是相同的连接。
从系统接口的角度来看,您不能创建这种情况,因为系统不允许您将已在使用的地址/端口对绑定到任何套接字(比严格要求的约束更强)。这意味着一台机器不能同时为客户端套接字和服务器套接字使用相同的端口,即使对于不同的远程端点也是如此。
但是,您可以同时拥有任意数量的 TCP 连接,每个连接至少在其中一个参数上与所有其他连接不同。特别是,您可以在相同的两台机器之间建立任意数量的连接,一侧使用相同的端口,另一侧使用不同的端口。事实上,这是非常常见的,因为 Web 浏览器通常会同时打开多个到 Web 服务器的连接以同时下载多个资源。所有这些连接都具有相同的服务器地址、服务器端口和客户端地址,但客户端端口不同。
如果您想要同时建立多个连接,这些连接以某种超出 IP 地址的方式相互关联,那么您需要为其开发一种协议,至少在一端涉及多个端口。如果机器建立相互连接,A 连接到 B,然后 B 分别连接到 A,那么两边都需要不同的端口。要使用的端口号可能由协议固定或以某种方式协商,由您自行决定,但问题中描述的细节不是一个选项。
你不能打开一个既能监听又能连接的套接字。
我正在使用 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: Invalid argument"。我假设这是由于该端口已被使用。有什么方法可以绕过这个,或者有什么方法可以将服务器连接到客户端,并允许客户端也使用相同的端口充当服务器
TCP 连接由其两个端点标识。反过来,每一个都由一对(IP 地址、端口)标识。因此,您不能同时在两端具有相同端口的相同两个 IP 地址之间建立两个不同的连接——如果所有这些属性都相同,那么它们就是相同的连接。
从系统接口的角度来看,您不能创建这种情况,因为系统不允许您将已在使用的地址/端口对绑定到任何套接字(比严格要求的约束更强)。这意味着一台机器不能同时为客户端套接字和服务器套接字使用相同的端口,即使对于不同的远程端点也是如此。
但是,您可以同时拥有任意数量的 TCP 连接,每个连接至少在其中一个参数上与所有其他连接不同。特别是,您可以在相同的两台机器之间建立任意数量的连接,一侧使用相同的端口,另一侧使用不同的端口。事实上,这是非常常见的,因为 Web 浏览器通常会同时打开多个到 Web 服务器的连接以同时下载多个资源。所有这些连接都具有相同的服务器地址、服务器端口和客户端地址,但客户端端口不同。
如果您想要同时建立多个连接,这些连接以某种超出 IP 地址的方式相互关联,那么您需要为其开发一种协议,至少在一端涉及多个端口。如果机器建立相互连接,A 连接到 B,然后 B 分别连接到 A,那么两边都需要不同的端口。要使用的端口号可能由协议固定或以某种方式协商,由您自行决定,但问题中描述的细节不是一个选项。
你不能打开一个既能监听又能连接的套接字。