【问题标题】:Program does not send UDP package on specified port程序不在指定端口上发送 UDP 包
【发布时间】:2021-10-24 18:09:06
【问题描述】:

我是套接字编程的新手。我想将 UDP 包发送到网络中另一台 PC 上的特定端口。当我使用 Wireshark 分析我的网络流量时,我看到传出包中的端口号与我在代码中指定的端口号不同。 使用 port=10000 时,它发送到的实际端口是 4135。当我将其更改为 port=15000(只是为了尝试不同的东西)时,它会发送到端口 38970。

wireshark 显示的端口号必须为真,因为设置为侦听这些端口(4135 或 38970)的接收程序确实会对发送的包做出反应,尽管接收到的数据看起来像乱码(控制台显示未知字符,调试控制台显示“1\355I\211\321^H\211...”)。

有什么想法吗?

我在连接到虚拟网络中其他 VM 的 Debian VM 上运行它。使用 TCP 的一个非常相似的程序运行良好。

#include <sys/types.h>      //Various types, including ssize_t
#include <sys/socket.h>     //Types, macros and functions for sockets
#include <netinet/in.h>     //Types, including sockaddr_in, macros
#include <arpa/inet.h>      //Types and functions, including inet_aton()
#include <unistd.h>         //Types, macros and functions for Unix/Posix
#include <stdlib.h>         //GP types, macros and functions
#include <stdio.h>          //IO operations (streams)
#include <string.h>         //Functions for string operations
 
#define BC_ADDR "192.168.1.255"
 
int main(int argc, char** argv) {
    int                 clientSocket;
    const int           setBroadcast = 1;
    in_port_t           port = 10000;
    struct sockaddr_in  broadcastAddr;
    int                 broadcastAddrLen = sizeof(struct sockaddr_in);
    const char*         msg = "Hello World";
 
    //Create a new UDP socket
    clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
    if(clientSocket > 0) {
        printf("Socket created successfully\n");
    }
    else {
        printf("Failure during socket creation\n");
        exit(EXIT_FAILURE);
    }
 
    //Set socket options to allow broadcasts
    int setSockOptStatus = setsockopt(clientSocket, SOL_SOCKET, 
        SO_BROADCAST, &setBroadcast, sizeof(setBroadcast));
    if(setSockOptStatus != 0) {
        printf("Error setting socket options!");
        close(clientSocket);
        return EXIT_FAILURE;
    }
 
    //Form boradcast address structure
    broadcastAddr.sin_family = AF_INET;
    broadcastAddr.sin_port   = port;
    broadcastAddr.sin_addr.s_addr = inet_addr(BC_ADDR);
 
    //Send broadcast message
    sendto(clientSocket, msg, strlen(msg)+1, 0, 
           (struct sockaddr*) &broadcastAddr, broadcastAddrLen);
 
    //Close socket and exit program
    close(clientSocket);
    return EXIT_SUCCESS;    
}

【问题讨论】:

  • 您不会错误检查sendto() 调用——是否有充分的理由忽略它?请注意,您通常应该将错误消息写入stderr,而不是stdout。并且消息应该以换行符结尾,以便及时显示输出。
  • 您说您正在编写 C++ 程序,但显示的代码似乎是 C 而不是(惯用的)C++。我没有立即在代码中看到任何独特的 C++ 功能。通常,避免同时使用 C 和 C++ 标记问题;它往往会惹恼那些可能会回答的人。
  • 我忘记了 sendto() 的错误检查。我添加了它,它返回“12”。所以这里没有错误。

标签: c sockets networking


【解决方案1】:

问题在于您如何设置端口:

broadcastAddr.sin_port   = port;

struct sockaddr_in 中存储的 IP 地址和端口号都必须采用 网络字节顺序,即大端字节顺序,即最高有效字节在前。您的机器显然使用 little-endian 字节排序,即最低有效字节在前,因此通过将端口号直接分配给 sin_port 成员,转换未完成。

如果您查看预期端口号和实际端口号的十六进制表示,这一点会更加明显:

  • 10000d = 2710h, 4135d = 1027h
  • 15000d = 3a98h, 38970 = 983ah

您需要调用htons()函数,它将一个16位的值从主机字节顺序转换为网络字节顺序:

broadcastAddr.sin_port   = htons(port);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 2023-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    相关资源
    最近更新 更多