UDP 客户端(接收器)未按预期接收数据报



我正在尝试从一个程序(具体为X-Plane 10)接收数据。它应该通过UDP连接完成。 XPlane 发送的数据格式为 (4 + n * 32) 字节包(n- 取决于 Xplane 内部的设置)。 我正在尝试通过以下代码接收它:

const int LEN = 256;
int server_length;
int port = 49010;
char* package = new char[LEN];
WSADATA wsaData;
SOCKET mySocket;
SOCKET myBackup;
SOCKET acceptSocket;
sockaddr_in myAddress;
int _tmain(int argc, _TCHAR* argv[])
{
//socket
if( WSAStartup( MAKEWORD(2, 2), &wsaData ) != NO_ERROR )
{
cerr<<"Socket Initialization: Error with WSAStartupn";
system("pause");
WSACleanup();
exit(10);
}
mySocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (mySocket == INVALID_SOCKET)
{
cerr<<"Error creating socket"<<endl;
system("pause");
WSACleanup();
exit(11);
}

//binding
myAddress.sin_family = AF_INET;
myAddress.sin_addr.s_addr = inet_addr( "127.0.0.1" );
myAddress.sin_port = htons(port);
if(bind(mySocket, (SOCKADDR*) &myAddress, sizeof(myAddress)) == SOCKET_ERROR)
{
cerr<<"Failed to connectn";
system("pause");
WSACleanup();
exit(14);
}
//receiving
while (true) 
{
cout.flush();
server_length = sizeof(struct sockaddr_in);
myAddress.sin_port = htons(port);
recvfrom(mySocket, package, LEN, 0, (SOCKADDR*) &myAddress, &server_length);
printf( "%sn", package );
}
return 0;
}

我收到的只是DATA@+有时是一个随机符号。

我知道数据报的前 5 个字节应该是"DATA@",所以我知道它正在连接并且或多或少可以工作,但我不明白为什么它不读取 Xplane 发送的其余数据。

编辑: 我在网上找到了一个代码,并在我的程序中使用了它。相同的结果:DATA@...

它也不会在文件中显示任何其他内容。

#define DEFAULT_PORT            49010
#define DEFAULT_COUNT           100
#define DEFAULT_BUFFER_LENGTH   41
int   iPort    = DEFAULT_PORT;          // Port to receive on
DWORD dwCount  = DEFAULT_COUNT,         // Number of messages to read
dwLength = DEFAULT_BUFFER_LENGTH; // Length of receiving buffer
BOOL  bInterface = FALSE;               // Use an interface other than
// default
char  szInterface[32];            // Interface to read datagrams from
//
// Function: usage:
//
// Description:
//    Print usage information and exit
//
void usage()
{
printf("usage: sender [-p:int] [-i:IP][-n:x] [-b:x]nn");
printf("       -p:int   Local portn");
printf("       -i:IP    Local IP address to listen onn");
printf("       -n:x     Number of times to send messagen");
printf("       -b:x     Size of buffer to sendnn");
ExitProcess(1);
}
//
// Function: ValidateArgs
//
// Description:
//    Parse the command line arguments, and set some global flags to
//    indicate what actions to perform
//
void ValidateArgs(int argc, char **argv) 
{
int                i;
for(i = 1; i < argc; i++)
{
if ((argv[i][0] == '-') || (argv[i][0] == '/'))
{
switch (tolower(argv[i][1]))
{
case 'p':   // Local port
if (strlen(argv[i]) > 3)
iPort = atoi(&argv[i][3]);
break;
case 'n':   // Number of times to receive message
if (strlen(argv[i]) > 3)
dwCount = atol(&argv[i][3]);
break;
case 'b':   // Buffer size
if (strlen(argv[i]) > 3)
dwLength = atol(&argv[i][3]);
break;
case 'i':   // Interface to receive datagrams on
if (strlen(argv[i]) > 3)
{
bInterface = TRUE;
strcpy(szInterface, &argv[i][3]);
}
break;
default:
usage();
break;
}
}
}
}
//
// Function: main
//
// Description:
//    Main thread of execution. Initialize Winsock, parse the command
//    line arguments, create a socket, bind it to a local interface
//    and port, and then read datagrams.
//
int main(int argc, char **argv)
{
WSADATA        wsd;
SOCKET         s;
char          *recvbuf = NULL;
int            ret,
i;
int          dwSenderSize;
SOCKADDR_IN    sender,
local;
// Parse arguments and load Winsock
//
ValidateArgs(argc, argv);
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("WSAStartup failed!n");
return 1;
}
// Create the socket and bind it to a local interface and port
//
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == INVALID_SOCKET)
{
printf("socket() failed; %dn", WSAGetLastError());
return 1;
}
local.sin_family = AF_INET;
local.sin_port = htons((short)iPort);
if (bInterface)
local.sin_addr.s_addr = inet_addr(szInterface);
else
local.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, (SOCKADDR *)&local, sizeof(local)) == SOCKET_ERROR)
{
printf("bind() failed: %dn", WSAGetLastError());
return 1;
}
// Allocate the receive buffer
//
recvbuf = (char*)GlobalAlloc(GMEM_FIXED, dwLength);
if (!recvbuf)
{
printf("GlobalAlloc() failed: %dn", GetLastError());
return 1;
}
// Read the datagrams
//
std::ofstream myfile;
myfile.open ("file.txt");

for(i = 0; i < dwCount; i++)
{
dwSenderSize = sizeof(sender);
ret = recvfrom(s, recvbuf, dwLength, 0,
(SOCKADDR *)&sender, &dwSenderSize);
if (ret == SOCKET_ERROR)
{
printf("recvfrom() failed; %dn", WSAGetLastError());
break;
}
else if (ret == 0)
break;
else
{
recvbuf[ret] = '';
printf("[%s] sent me: '%s'n",
inet_ntoa(sender.sin_addr), recvbuf);
myfile << recvbuf<<endl;
}
}
closesocket(s);
GlobalFree(recvbuf);
WSACleanup();
myfile.close();
return 0;
}
printf( "%sn", package );

这是一个 C 样式函数,它期望获取一个 C 样式字符串,以字节结尾。

显示的代码使用new分配此package缓冲区,并且无法清除或初始化此缓冲区。因此,package的初始内容是随机垃圾。然后,显示的代码在缓冲区中接收一些数据:

recvfrom(mySocket, package, LEN, 0, (SOCKADDR*) &myAddress, &server_length);

recvfrom() 返回接收的实际字节数,但显示的代码完全忽略了这一点。因此,任何实际接收到的东西都会被放入package,其余的package缓冲区仍然包含它最初包含的上述随机垃圾。

显示的代码中没有任何内容可以正确附加在收到的数据包中的最后一个字节之后。因此,当显示的代码尝试printfpackage指针时,recvfrom()的实际内容将跟在缓冲区中的任何随机垃圾之后,直到printf幸运地找到一些,在那里的某个地方。

相关内容

最新更新