如何强制 udp 服务器接收到的 udp 客户端套接字绑定到特定的客户端端口
How do I force a udp client socket received by a udp server to bind to a specific client port
我需要通过udp连接两个程序。这是工作的方式是两个程序都是 udp 服务器,它们在两个端口上发送和接收,如下所示:
programA 在端口 20037 上侦听并在端口 20038 上发送。
programB 在端口 20038 上侦听并在端口 20037 上发送。
程序 A 和程序 B 运行 在同一台计算机上。
programA 已经编写,它似乎确实像上面那样绑定了它的套接字。即传输端口 = 20038 和监听端口 = 20037.
我写了一个udp程序作为程序B。
我的程序 B 将服务器套接字绑定到正确的端口 20038。
但是当 programB 收到来自 programA 的消息时,客户端套接字似乎绑定到某个随机端口,例如端口 10690。但我需要它绑定到端口 20037。
使用的协议,需要在收到消息时发回一个简单的确认消息。
我的代码如下所示:
struct sockaddr_in client;
char buffer[BUFFER_SIZE];
/* Loop and get data from clients */
while (1)
{
int client_length = (int)sizeof(struct sockaddr_in);
/* Receive bytes from client */
int bytes_received = recvfrom(sd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &client_length);
if (bytes_received < 0)
{
fprintf(stderr, "Could not receive datagram.\n");
closesocket(sd);
WSACleanup();
exit(0);
}
printf("%u bytes received from client on port %u\n", bytes_received, client.sin_port);
SendAck();
}
而 SendAck() 是这样的:
void udpserver::SendAck() {
unsigned char acker[] = { SOM, ACK };
int length = sizeof(acker)/sizeof(acker[0]);
int client_length = (int)sizeof(struct sockaddr_in);
if (sendto(sd, (const char*)acker, length, 0, (struct sockaddr *)&client, client_length) == -1)
{
fprintf(stderr, "Error transmitting data.\n");
closesocket(sd);
WSACleanup();
exit(0);
}
else
printf("successfully sent ack to client\n");
}
我假设接收到的客户端套接字的端口号是 20037,但它是一个随机数。我可以强制客户端套接字绑定到端口 20037 吗?因为ack报文要发到20037端口。
而且我无法更改此设计。 ProgramA 将始终绑定到侦听端口 20037,并通过将其客户端端口绑定到 20038 来发送。我可以自由地执行 programB 所需的任何操作。
将套接字绑定到要用作出站端口的端口:
client.sin_port = htons(20037);
然后发送:
sendto(sd, (const char*) acker, length, 0,
(struct sockaddr*) &client, client_length);
recvfrom()
报告发送接收数据包的远程 IP/port。 ProgramA 正在从端口 20038 发送数据。SendAck()
使用 recvfrom()
提供的客户端信息调用 sendto()
,这意味着 ACK 被发送到端口 20038,而不是端口 20037。
UDP 系统将回复发送到与发送端口不同的端口是不正常的。但就这样吧。您必须告诉 sendto()
要发送到哪个端口。
您也没有正确记录发件人的端口。 client.sin_port
以网络字节顺序表示。记录时使用 ntohs()
将其更改为主机字节顺序。如果不这样做,就会导致您看到的 随机 数字。
试试这个:
struct sockaddr_in client;
char buffer[BUFFER_SIZE];
/* Loop and get data from clients */
while (1)
{
int client_length = (int)sizeof(struct sockaddr_in);
/* Receive bytes from client */
int bytes_received = recvfrom(sd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &client_length);
if (bytes_received < 0)
{
fprintf(stderr, "Could not receive datagram.\n");
closesocket(sd);
WSACleanup();
exit(0);
}
printf("%u bytes received from client at %s on port %u\n", bytes_received, inet_ntoa(client.sin_addr), ntohs(client.sin_port));
SendAck(&client);
}
void udpserver::SendAck(struct sockaddr_in *client)
{
struct sockaddr_in receiver;
memcpy(&receiver, client, sizeof(struct sockaddr_in));
receiver.sin_port = htons(20037);
unsigned char acker[] = { SOM, ACK };
int length = sizeof(acker)/sizeof(acker[0]);
if (sendto(sd, (const char*)acker, length, 0, (struct sockaddr *)&receiver, sizeof(struct sockaddr_in)) == -1)
{
fprintf(stderr, "Error transmitting data.\n");
closesocket(sd);
WSACleanup();
exit(0);
}
else
printf("successfully sent ack to client at %s on port %d\n", inet_ntoa(receiver.sin_addr), ntohs(receiver.sin_port));
}
我需要通过udp连接两个程序。这是工作的方式是两个程序都是 udp 服务器,它们在两个端口上发送和接收,如下所示:
programA 在端口 20037 上侦听并在端口 20038 上发送。 programB 在端口 20038 上侦听并在端口 20037 上发送。
程序 A 和程序 B 运行 在同一台计算机上。
programA 已经编写,它似乎确实像上面那样绑定了它的套接字。即传输端口 = 20038 和监听端口 = 20037.
我写了一个udp程序作为程序B。
我的程序 B 将服务器套接字绑定到正确的端口 20038。
但是当 programB 收到来自 programA 的消息时,客户端套接字似乎绑定到某个随机端口,例如端口 10690。但我需要它绑定到端口 20037。
使用的协议,需要在收到消息时发回一个简单的确认消息。
我的代码如下所示:
struct sockaddr_in client;
char buffer[BUFFER_SIZE];
/* Loop and get data from clients */
while (1)
{
int client_length = (int)sizeof(struct sockaddr_in);
/* Receive bytes from client */
int bytes_received = recvfrom(sd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &client_length);
if (bytes_received < 0)
{
fprintf(stderr, "Could not receive datagram.\n");
closesocket(sd);
WSACleanup();
exit(0);
}
printf("%u bytes received from client on port %u\n", bytes_received, client.sin_port);
SendAck();
}
而 SendAck() 是这样的:
void udpserver::SendAck() {
unsigned char acker[] = { SOM, ACK };
int length = sizeof(acker)/sizeof(acker[0]);
int client_length = (int)sizeof(struct sockaddr_in);
if (sendto(sd, (const char*)acker, length, 0, (struct sockaddr *)&client, client_length) == -1)
{
fprintf(stderr, "Error transmitting data.\n");
closesocket(sd);
WSACleanup();
exit(0);
}
else
printf("successfully sent ack to client\n");
}
我假设接收到的客户端套接字的端口号是 20037,但它是一个随机数。我可以强制客户端套接字绑定到端口 20037 吗?因为ack报文要发到20037端口。
而且我无法更改此设计。 ProgramA 将始终绑定到侦听端口 20037,并通过将其客户端端口绑定到 20038 来发送。我可以自由地执行 programB 所需的任何操作。
将套接字绑定到要用作出站端口的端口:
client.sin_port = htons(20037);
然后发送:
sendto(sd, (const char*) acker, length, 0,
(struct sockaddr*) &client, client_length);
recvfrom()
报告发送接收数据包的远程 IP/port。 ProgramA 正在从端口 20038 发送数据。SendAck()
使用 recvfrom()
提供的客户端信息调用 sendto()
,这意味着 ACK 被发送到端口 20038,而不是端口 20037。
UDP 系统将回复发送到与发送端口不同的端口是不正常的。但就这样吧。您必须告诉 sendto()
要发送到哪个端口。
您也没有正确记录发件人的端口。 client.sin_port
以网络字节顺序表示。记录时使用 ntohs()
将其更改为主机字节顺序。如果不这样做,就会导致您看到的 随机 数字。
试试这个:
struct sockaddr_in client;
char buffer[BUFFER_SIZE];
/* Loop and get data from clients */
while (1)
{
int client_length = (int)sizeof(struct sockaddr_in);
/* Receive bytes from client */
int bytes_received = recvfrom(sd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &client_length);
if (bytes_received < 0)
{
fprintf(stderr, "Could not receive datagram.\n");
closesocket(sd);
WSACleanup();
exit(0);
}
printf("%u bytes received from client at %s on port %u\n", bytes_received, inet_ntoa(client.sin_addr), ntohs(client.sin_port));
SendAck(&client);
}
void udpserver::SendAck(struct sockaddr_in *client)
{
struct sockaddr_in receiver;
memcpy(&receiver, client, sizeof(struct sockaddr_in));
receiver.sin_port = htons(20037);
unsigned char acker[] = { SOM, ACK };
int length = sizeof(acker)/sizeof(acker[0]);
if (sendto(sd, (const char*)acker, length, 0, (struct sockaddr *)&receiver, sizeof(struct sockaddr_in)) == -1)
{
fprintf(stderr, "Error transmitting data.\n");
closesocket(sd);
WSACleanup();
exit(0);
}
else
printf("successfully sent ack to client at %s on port %d\n", inet_ntoa(receiver.sin_addr), ntohs(receiver.sin_port));
}