首页 > 解决方案 > C UDP套接字连接没有正确分配端口

问题描述

我有以下架构:

program in terminal A (<process 1>):

Stored:
    <process 1>: <portnumber 51340>
    <process 2>: <portnumber 58432>

program in terminal B (<process 2>):

Stored:
    <process 1>: <portnumber 51340>
    <process 2>: <portnumber 58432>

所以我在它们之间有一个 UDP 套接字连接来发送和接收一个结构:

  int socketID = socket(AF_INET, SOCK_DGRAM, 0);
  struct sockaddr_in servaddr = {0};

  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(0);
  servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

  int rc = bind(socketID, (const struct sockaddr *)&servaddr, sizeof(servaddr));
  socklen_t sockaddrlen = sizeof(servaddr);
  int getsocket = getsockname(socketID, (struct sockaddr *)&servaddr, &sockaddrlen);

在我进行 sendto 之前,我会:

fprintf(stdout, "Using procPort %d\n", idPort);
servaddr.sin_port = htons(<portNumber 58432>);
fprintf(stdout, "Using port %d\n", &toSocketID.sin_port);
sendto(fromSocketID, &msg, sizeof(struct message), 0, (const struct sockaddr *)&toSocketID, toSocketIDLen);

它打印:

Using procPort 58432
Using port 58432

直到这里一切正常。这是问题所在,在我执行 recvfrom 之前,我会这样做:

servaddr.sin_port = htons(<portNumber 58432>);
fprintf(stdout, "Using procPort %d\n", <portNumber 58432>);
fprintf(stdout, "Using port %d\n", servaddr.sin_port);

struct message * recievedMsg = malloc(sizeof(struct message));

recieveResult = recvfrom(socketID, recievedMsg, sizeof(*recievedMsg), 0, (const struct sockaddr *)&servaddr, sizeof(servaddr));

它打印:

Using procPort 58432
Using port 16612

而且它没有收到消息,我认为这是因为端口的神奇变化,即 16612 没有出现在我的程序中的任何位置。但这也可能是因为配置。你看到有什么问题吗?我正在失去理智。

编辑:

你们中的一些人正在争论字节交换。第二部分的其他输出:

Using procPort 50912
Using port 57542

Using procPort 33592
Using port 14467

Using procPort 42115
Using port 33700

标签: csocketsstructudp

解决方案


这些片段很难真正了解全局,但我很确定您的编译器会告诉您问题所在。

struct sockaddr_in servaddr = {0};
...
receiveResult = recvfrom(socketID,
                         receivedMsg, sizeof(*receivedMsg),
                         0,
                         (const struct sockaddr *)&servaddr, sizeof(servaddr));

正如编译器所指出的,您将最后一个参数作为整数传递,但它应该是一个指针。这个想法是你告诉recvfrom你你的地址结构有多大,但在返回时内核告诉你它正在使用多少该结构。

我很惊讶它没有因为给出一个小整数作为指针而出错。

此外,倒数第二个参数不应该是const.

将其更改为(此处格式化只是为了便于阅读):

socklen_t addrsize = sizeof servaddr;

receiveResult = recvfrom(socketID,
                        receivedMsg, sizeof *receivedMsg,
                        0,
                        (struct sockaddr *)&servaddr, &addrsize);

编辑:故事的寓意:总是打开编译器警告并理解它们,而不仅仅是让它们消失。随机转换可能会使编译器静音,但它会删除好的建议。

当你使用强制转换时,你是在告诉编译器“相信我”,如果你对编译器撒谎,它就会报复。

编辑 2:代码中的其他内容不可能是正确的。

我看不到类型toSocketID是什么,但我看不到任何正确的结构:

fprintf(stdout, "Using port %d\n", &toSocketID.sin_port);

我想ntohs(toSocketID->sin_port)似乎更合理。


推荐阅读