【问题标题】:Error with sendto() function: Invalid Argument Errorsendto() 函数出错:无效参数错误
【发布时间】:2020-09-16 06:51:09
【问题描述】:

我正在为 linux 编写一个 ping CLI 程序,我得到了 errno 22: invalid argument in the sendto() 函数。我不明白为什么,所有的论点似乎都是正确的。

这里是我调用函数的地方:

    // send echo request
    bytesSent = sendto(socketFD,                                                        // socket file descriptor
                      (char*)&packet, PacketSize,                                       // packet and size
                      0,                                                                // flags
                      (sockaddr*)DestinationAddr, (socklen_t)sizeof(DestinationAddr));  // destination address and size

“数据包”如下所示: (我在调用 sendto() 的函数中调用 initializePacket())

struct PacketData {
    icmphdr header;
    char message[PacketSize - sizeof(header)];      // want total size to be 64 bytes
};

PacketData initializePacket(int &transmitted) {
    PacketData packet = {};

    packet.header.type = ICMP_ECHO;                 // set ICMP type to Echo
    packet.header.un.echo.id = getpid() & 0xFFFF;   // set id (ICMP field is 16 bits)
    packet.header.checksum = 0;                     // fixed checksum because data is unchanging
    packet.header.un.echo.sequence = transmitted++;

    // fill up message
    memset(&packet.message, '0', sizeof(packet.message));
    packet.message[PacketSize - sizeof(packet.header) - 1] = '\0';

    return packet;
}

'DestinationAddr' 是这样的:

    // variables needed to store IP Address
    addrinfo* result;
    sockaddr_in* DestinationAddr;
    char ipString[INET_ADDRSTRLEN];

    // get IP Address and store in result (passed by reference)
    if (getIPAddress(argv[1], result) != 0) {
        std::cout << "Invalid IP Address. Terminating ...\n";
        exit(EXIT_FAILURE);
    }
    else {
        DestinationAddr = (sockaddr_in*)result->ai_addr;                        // get struct from resulting linked list
        void* address;
        address = &DestinationAddr->sin_addr;                                   // store IP Address
        inet_ntop(result->ai_family, address, ipString, sizeof(ipString));      // convert binary IP to string
        std::cout << "IP: " << ipString << std::endl;
    }

而getIPAddress()函数是:

int getIPAddress(char* hostName, addrinfo* &result) {
    addrinfo tempStruct = {0};

    tempStruct.ai_family = AF_INET;         // want IPv4
    tempStruct.ai_socktype = SOCK_DGRAM;    // set socket type to datagram
    tempStruct.ai_flags = AI_PASSIVE;       // fill in IP automatically

    // get and validate IP address
    return (getaddrinfo(hostName, &PortNo, &tempStruct, &result));
}

PortNo 定义为:const char PortNo = '0';

【问题讨论】:

  • 为什么要通过 UDP 发送 ICMP 数据包?
  • @user207421 我这样做是因为 UDP 在发送数据之前不需要建立连接,它最适合需要速度的时候,所以我认为这是最好的。

标签: sockets network-programming ping invalid-argument sendto


【解决方案1】:

根据文档icmp

用户协议可以通过使用 IPPROTO_ICMP 协议打开原始套接字来接收所有本地套接字的 ICMP 数据包。

所以,试着像这样创建你的套接字:

socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)

而且,如果您遇到 EPERM 错误,请以 root 身份运行您的程序。

【讨论】:

  • 我最初是这样做的:socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) 我也尝试过这样做,但它给出了同样的错误。 (错误号 22)
  • 我能够找到错误。这是因为我在指针上调用 sizeof() - DestinationAddr - 我取消引用它并且无效参数错误消失了。现在,它成功发送了数据(sendto() 返回 64),但它没有接收到数据。超时导致它结束,如果我删除超时,那么它只会继续等待数据。 (给出errno 11(资源暂时不可用))
猜你喜欢
  • 1970-01-01
  • 2018-10-11
  • 2018-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-04
  • 2019-01-25
  • 2012-08-01
相关资源
最近更新 更多