繁体   English   中英

如何强制 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 上发送。

programA 和 programB 都运行在同一台计算机上。

programA 已经写好了,它确实像上面那样绑定了它的套接字。 即传输端口 = 20038 和侦听端口 = 20037。

我写了一个udp程序作为programB。

我的程序 B 将服务器套接字绑定到端口 20038,这是正确的。

但是当 programB 收到来自 programA 的消息时,客户端套接字似乎绑定到某个随机端口,例如端口 10690。但我需要它绑定到端口 20037。

使用的协议,需要在收到消息时发回一个简单的 ack 消息。

我的代码如下所示:

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/端口发送的。 ProgramA 正在从端口 20038 发送数据。 SendAck()正在使用recvfrom()提供的客户端信息调用sendto() recvfrom() ,这意味着 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));
}

暂无
暂无

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

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