【问题标题】:C++ Winsock UDP sendto succeeds but I don't see the data being sentC++ Winsock UDP sendto 成功,但我没有看到正在发送的数据
【发布时间】:2017-01-19 18:06:33
【问题描述】:

我正在我的工作站 (192.168.0.1) 和我的 WinCE6 设备 (192.168.0.100) 之间的以太网接口上使用 UDP 套接字。

我可以从我的工作站向我的 WinCE 设备发送 UDP 数据包,在那里我设置了接收套接字并在端口 9002 上正确接收数据;然后设备会正确地将数据回显到我的工作站。

我希望我的设备在特定端口上应答我的工作站:9001。

这是运行到我设备中的服务器,它与this 相同,但我修改了套接字绑定到特定接口的地址并更改了PORT 定义:

#define BUFLEN 512  //Max length of buffer
#define PORT 9002   //The port on which to listen for incoming data

void test_udp( void )
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen , recv_len;
char buf[BUFLEN];
WSADATA wsa;

slen = sizeof(si_other) ;

//Initialise winsock
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
    return;
}

//Create a socket
if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
{
    printf( "Could not create socket : %d" , WSAGetLastError());
}

//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl( 0xC0A80064 );
server.sin_port = htons( PORT );

//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
    return;
}

//keep listening for data
while(1)
{
    //clear the buffer by filling null, it might have previously received data
    memset(buf,'\0', BUFLEN);

    //try to receive some data, this is a blocking call
    if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
    {
        return;
    }

    // *** CHANGE THE SEND PORT
    si_other.sin_port = htons( 9001 );

    //now reply the client with the same data
    if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == SOCKET_ERROR)
    {
        return;
    }
}

closesocket(s);
WSACleanup();

return;
}

当我在// *** CHANGE THE SEND PORT 注释下方添加一行以尝试将数据发送回端口 9001 时,我得到了与我期望发送的字节数相匹配的 sendto 的适当返回值,但我没有看到我的工作站上的数据(在 9001 上收听)。

我一直在努力反对这一点,但我看不出有什么问题。在修改后的示例中,任何帮助将不胜感激。

更新:我的开发 PC 上的防火墙出现故障。它允许我的 PC 发送的同一端口上的流量返回,但阻止任何其他端口上的流量。解决该问题允许在不更改代码的情况下发送流量。我之前禁用了防火墙,但没有意识到操作系统已将以太网标记为“公共网络”,但仍然启用了防火墙。

【问题讨论】:

  • 您如何知道您的接收程序正在运行?您是否尝试过使用wireshark 来查看是什么击中了电线?如果您打印出sendto() 的返回码也会很有帮助,因为很难判断它是否失败。
  • 首先要做的是检查绑定并使用 WSAGetLastError。随时检查打印的第二件事,例如:是否收到消息。使用阻塞函数来接收和发送。我曾经做过的最好的事情是我使用 udp 套接字和多线程制作了一个聊天程序
  • 你为什么要换sin_port?它已经包含recvfrom() 之后的发送端口号。那是您要回复的端口。删除该行。

标签: c++ sockets udp windows-ce winsock


【解决方案1】:

如果如您所说,您没有从 sendto 收到 SOCKET_ERROR 并且您看到了适当的返回值,这意味着您的操作系统能够找到通往目标 IP 的路由并且能够缓冲您的发送请求.

要更改发送端口,如果您想响应与您接收数据的端口不同的端口,这是可以的,但请注意,这不是典型情况; si_other 结构实际上将包含 recvfrom 之后的源地址,以及源端口。 所以请保持您的代码在设备端保持原样。

如果您在作为开发环境的简单网络环境中没有看到数据流向您的工作站,则问题出在工作站上:它没有接收数据
我同意@Daniel 的观点,您必须使用 WireShark 进行调查,以了解数据包发生了什么。

希望对你有帮助

【讨论】:

  • 1.如果您在发送时没有收到错误,则并不意味着找到了目标主机:端口。这只意味着有一条到主机的路由,并且数据报被缓冲发送。 2.设置sin_port不好:浪费时间。它已设置为回复的正确值。 '如果你会回答那个地址,你就会回答源端口'正是你想要做的。将sin_port 设置为某个固定值要么设置错误值,要么不更改正确值。
  • 感谢 EJP。但我不明白你为什么说改变 sin_port 设置错误的值或不改变它。这不是回答与我们收到的端口不同的端口的典型案例,但仍有可能......
  • sin_port 包含移植传入数据报的源。您应该响应的端口。设置它根本没有意义。您设置的值是错误的,在这种情况下响应不会到达,或者它是正确的,在这种情况下设置它什么也没做 - 它没有改变值。这似乎相当明显。问题中没有证据表明对等方正在使用两个端口,因此没有理由建议您保留代码。
  • 好的,我明白了。您是说可以更改目标端口,但您认为情况并非如此。然而,我读到的是,Briggs 能够从他的开发机器发送到移动设备上的端口 9002,并看到数据在端口 9002 上的开发机器上回显。之后,他将开发机器上的代码更改为监听 9001。似乎他想从开发机器接收(来自任何端口的通信)并回复 9001。这就是我建议保留代码的原因。
  • 然而,“错误”可能是 Briggs 从未在开发机器上的端口 9002 上接收到数据,但他总是在用于启动通信的源端口上接收到开发机器上的数据(正如预期的那样典型)。所以@Briggs 对我来说,你必须弄清楚你的目标客户端服务器架构是什么......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-25
相关资源
最近更新 更多