((Winsock)UDP接收正常,但对于同一套接字发送失败

问题描述 投票:0回答:1

我在Windows中使用UDP套接字时遇到问题。我有一个单独的应用程序,试图与端口1625上的输出进行通信,并在端口26027上进行接收。我试图制作一个简单的可执行文件,该文件可以读取一条消息并发送一条消息。读取工作正常,但发送最终出现WSAEADDRNOTAVAIL(10049)错误。

要进行故障排除,我还在同一台计算机上(使用Linux的Windows子系统)尝试了Linux中的等效代码,并且工作正常。所以我不知道是什么问题。我还尝试禁用Windows防火墙,但这并没有改变。任何建议,将不胜感激。

Windows Visual C ++代码:

#pragma comment(lib, "Ws2_32.lib")

#include <iostream>
#include <WS2tcpip.h>

#define MAXLINE 1024

int main()
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    // Define local port address.
    sockaddr_in local_port;
    memset(&local_port, 0, sizeof(local_port));
    local_port.sin_family = AF_INET;
    local_port.sin_addr.s_addr = INADDR_ANY;
    local_port.sin_port = htons(1625);

    // Bind local socket.
    int socket_id = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    bind(socket_id, (const struct sockaddr *)&local_port, sizeof(local_port));

    // Receive UDP Port message.
    char in_buffer[MAXLINE];
    int num_bytes = recv(socket_id, (char *)in_buffer, MAXLINE, 0);
    in_buffer[num_bytes] = '\0';
    printf("Received : %s\n", in_buffer);

    // Set up send destination port.
    sockaddr_in dest_port;
    memset(&dest_port, 0, sizeof(dest_port));
    dest_port.sin_family = AF_INET;
    dest_port.sin_addr.s_addr = INADDR_ANY;
    dest_port.sin_port = htons(26027);

    // Send UDP message to specific UDP port.
    char out_buffer[] = "Test message";
    int result = sendto(
        socket_id, out_buffer, strlen(out_buffer), 0, (struct sockaddr *)&dest_port, sizeof(dest_port));
    printf("Send result : %d -- WSA Error : %d\n", result, WSAGetLastError());

    closesocket(socket_id);
    return 0;
}

运行此可执行文件的终端输出是:

Received : 5e4009df*755=-0.0028:761=0.6942

Send result : -1 -- WSA Error : 10049

WSL linux C ++代码(除了WSA包含和错误输出,其他源代码相同:]

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define MAXLINE 1024

int main()
{
    // Define local port address.
    sockaddr_in local_port;
    memset(&local_port, 0, sizeof(local_port));
    local_port.sin_family = AF_INET;
    local_port.sin_addr.s_addr = INADDR_ANY;
    local_port.sin_port = htons(1625);

    // Bind local socket.
    int socket_id = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    bind(socket_id, (const struct sockaddr *)&local_port, sizeof(local_port));

    // Receive UDP Port message.
    char in_buffer[MAXLINE];
    int num_bytes = recv(socket_id, (char *)in_buffer, MAXLINE, 0);
    in_buffer[num_bytes] = '\0';
    printf("Received : %s\n", in_buffer);

    // Set up send destination port.
    sockaddr_in dest_port;
    memset(&dest_port, 0, sizeof(dest_port));
    dest_port.sin_family = AF_INET;
    dest_port.sin_addr.s_addr = INADDR_ANY;
    dest_port.sin_port = htons(26027);

    // Send UDP message to specific UDP port.
    char out_buffer[] = "Test message";
    int result = sendto(
        socket_id, out_buffer, strlen(out_buffer), 0, (struct sockaddr *) &dest_port, sizeof(dest_port));
    printf("Send result : %d\n", result);

    close(socket_id);
    return 0;
}

运行此可执行文件的终端输出是:

Received : 5e4009df*755=-0.0028:761=0.6942

Send result : 12

我还可以验证通过该Linux实现到端口26027的输出是否已被其他应用程序接收,也可以在Wireshark中看到它。

编辑:在下面雷米(Remy)的回答之后,我能够按照以下评论进行操作。为了澄清我的网络:

如果使用Wireshark查看,我的网络现在看起来像:

127.0.0.1   UDP 50223 → 1625 Len=32  
127.0.0.1   UDP 1625 → 26027 Len=12  

[我的节点绑定到1625时,它可以从某个未知端口号(在这种情况下为50223)和recv()端口26027来sendto() UDP。

c++ udp winsock
1个回答
2
投票

除非首先调用recv()将对等方的IP /端口静态分配给该套接字,否则您不能将connect()与UDP套接字一起使用,这是您没有做的。因此,recv()将失败,但是您没有对此进行检查。您需要改用recvfrom()

而且,无论如何,您都无法照原样将数据包发送到INADDR_ANY(0.0.0.0)。这就是为什么您会收到发送错误的原因。

sendto Function

WSAEADDRNOTAVAIL

远程地址不是有效地址,例如,ADDR_ANY

Windows Sockets Error Codes

WSAEADDRNOTAVAIL10049

无法分配请求的地址。 所请求的地址在其上下文中无效。通常是由于尝试绑定到对本地计算机无效的地址而导致的。 这也可能是由于远程计算机上的远程地址或端口无效(例如,地址或端口0)时,connect,sendto,WSAConnect,WSAJoinLeaf或WSASendTo导致的结果。]

您需要发送到实际的IP /端口,例如recvfrom()收到数据包时报告的对等方的IP /端口。

© www.soinside.com 2019 - 2024. All rights reserved.