【问题标题】:Issue receiving UDP packets接收 UDP 数据包的问题
【发布时间】:2017-06-28 11:45:40
【问题描述】:

我正在尝试读取本地连接到笔记本电脑的硬件设备发送的 UDP 数据包的内容。

在 Visual Studio 中,我编写了一个快速的 w32 控制台应用程序,只是为了读取 UDP 数据包:

WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0) 
{
    MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
    exit(1);
}
SOCKADDR_IN addr; 
int sizeofaddr = sizeof(addr); 
addr.sin_addr.s_addr = inet_addr("192.168.1.1");
addr.sin_port = htons(1234); 
addr.sin_family = AF_INET; 

SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL); //Create socket to listen for new connections
bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); //Bind the address to the socket
listen(sListen, SOMAXCONN); //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Oustanding Max Connections

SOCKET Connection = socket(AF_INET, SOCK_STREAM, NULL); //Set Connection socket
if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0) //If we are unable to connect...
{
    MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR);
    return 0; //Failed to Connect
}
std::cout << "Connected!" << std::endl;

char MOTD[1280];
recvfrom(Connection, MOTD, sizeof(MOTD), 217, (SOCKADDR *)&addr, &sizeofaddr);
std::cout << "Done:" << MOTD << std::endl;

while (true)
{
    Sleep(10);
}

输出是:

如果我从笔记本电脑上拔下设备,我仍然会得到相同的结果。

我可以在 wireshark 中看到带有数据的 UDP 数据包,从那边看一切都很好。

任何想法我做错了什么?是否有任何其他方式来接收来自网络的 UDP 数据包?

【问题讨论】:

  • 你能用符号作为标志吗217是什么标志?
  • 你没有检查recvfrom的值。
  • 嗨,理查德,对不起,我确实发布了错误的函数,实际上我得到了:recvfrom(Connection, MOTD, sizeof(MOTD), 0, (SOCKADDR *)&addr, &sizeofaddr);标志是 0

标签: c++ sockets udp wireshark


【解决方案1】:

接收 UDP 数据包问题

这里没有接收UDP数据包的代码。

我正在尝试读取本地连接到笔记本电脑的硬件设备发送的 UDP 数据包的内容。

在 Visual Studio 中,我编写了一个快速的 w32 控制台应用程序,只是为了读取 UDP 数据包:

不,你没有。

SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL); //Create socket to listen for new connections

这行代码创建了一个 TCP 套接字。它需要进行错误检查。

bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); //Bind the address to the socket

这行代码需要进行错误检查。

listen(sListen, SOMAXCONN); //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Oustanding Max Connections

这行代码将您的 TCP 套接字置于 LISTENING 状态。它需要进行错误检查。

SOCKET Connection = socket(AF_INET, SOCK_STREAM, NULL); //Set Connection socket

这行代码创建了另一个 TCP 套接字。它需要进行错误检查。

if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0) //If we are unable to connect...

这行代码将您的第二个 TCP 套接字连接到您的第一个 TCP 套接字的 IP 地址和端口。

到目前为止,与 UDP 没有任何关系。

recvfrom(Connection, MOTD, sizeof(MOTD), 217, (SOCKADDR *)&addr, &sizeofaddr);

这行代码从您的第二个已连接的 TCP 套接字接收。它需要一个错误检查:它还需要检查它的返回值是否为零,否则这个值应该用作接收到的数据的长度。但是,由于您从未接受过此连接,更不用说向接受的套接字发送任何内容,这行代码应该永远阻塞并且永远不会返回。

while (true)
{
    Sleep(10);
}

在网络代码中休眠实际上是在浪费时间。

输出是:

输出只是垃圾,因为您忽略了来自recvfrom() 的错误代码,可能是由于您似乎刚刚编造的flags 值217。如果你使用真正的MSG_* 值,你当然应该使用它们的名字。 217 中设置了五个位,即使是 TCP recv() 在 Winsock 中也只有三个有效标志。

我可以在 wireshark 中看到带有数据的 UDP 数据包,从那边看一切都很好。

这里与 UDP 数据包没有任何关系。您可能观察到的任何 UDP 数据包都来自其他地方,并且不可能被任何此代码接收或发送。

任何想法我做错了什么?

WSAStartup() 之后的所有内容。

有没有其他方法可以只接收来自网络的 UDP 数据包?

是的。使用SOCK_DGRAM 而不是SOCK_STREAM;不要调用listen(),不要创建两个套接字,不要调用connect()

【讨论】:

  • 感谢您的回答,我会尝试您的建议。
  • 你应该先看看 UDP 教程。你写的代码完全没有意义。
【解决方案2】:

根据 MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/ms740120(v=vs.85).aspx,接收函数只能使用 2 个值的有序组合:MSG_PEEK、MSG_OOB。

217 不仅仅是排列在一起的那两个标志。

您还应该真正检查函数的返回,如果出现错误,可以使用 WSAGetLastError 来查看问题是由什么引起的。

在调用 socket() 来创建 USB 套接字并且 UDP 是无连接的时,您还应该使用 SOCK_DGRAM 套接字类型 - 当前您正在使用 TCP,并连接到另一个 TCP 套接字(测试程序中的侦听套接字)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 2021-10-23
    • 2013-11-08
    相关资源
    最近更新 更多