Sockets 如何完全接收高速UDP数据包?
我有一个连续发送数据的UDP服务器。我想接收服务器发送的所有数据包 在服务器端,我有两个线程。一个线程不断地从文件中读取数据并将其放入deque。另一个线程从deque读取数据并连续发送到UDP客户端。客户端代码不断地从服务器接收数据 我有变量来记录服务器代码中发送的字节数和客户端代码中接收的字节数。 两者之间有着巨大的差异。服务器发送大约93MB,但客户端只接收3-5MB 如何接收服务器发送的所有数据 请在下面找到服务器和客户端代码 服务器代码:Sockets 如何完全接收高速UDP数据包?,sockets,visual-c++,udp,Sockets,Visual C++,Udp,我有一个连续发送数据的UDP服务器。我想接收服务器发送的所有数据包 在服务器端,我有两个线程。一个线程不断地从文件中读取数据并将其放入deque。另一个线程从deque读取数据并连续发送到UDP客户端。客户端代码不断地从服务器接收数据 我有变量来记录服务器代码中发送的字节数和客户端代码中接收的字节数。 两者之间有着巨大的差异。服务器发送大约93MB,但客户端只接收3-5MB 如何接收服务器发送的所有数据 请在下面找到服务器和客户端代码 服务器代码: #define MAX_BUFFER_SIZE
#define MAX_BUFFER_SIZE 1400
typedef struct
{
T_UCHAR buffer[MAX_BUFFER_SIZE];
DWORD buf_size;
}RAWDATA_LOG;
deque<RAWDATA_LOG> m_RawdataLog;
void TransmitContinuous()
{
if (m_sock_type_tcp == SOCK_UDP)
{
fileReadComplete=false;
//start data transmission thread
pWin_thread=AfxBeginThread(StartDataTransmitThread, (LPVOID) this);
ReadFromFile();
}
}
void ReadFromFile()
{
int bytesRead=0;
m_no_of_bytes = MAX_BUFFER_SIZE;
BYTE input_buf[MAX_BUFFER_SIZE]={'\0'};
GetDlgItemText(IDEBC_FILENAME,m_fileInput);
m_InputFile=NULL;
/*opening the file to read*/
m_InputFile = _tfopen(m_fileInput,L"rb");
if(m_InputFile == NULL)
{
AfxMessageBox(L"Unable to open the Input file");
}
else
{
while(!feof(m_InputFile))
{
bytesRead=fread(input_buf,1,m_no_of_bytes,m_InputFile);
writeRawdataToDeque(input_buf,m_no_of_bytes);
noofBytesReadfromFile+=bytesRead;
}
fileReadComplete=true;
}
}
void writeRawdataToDeque(T_UCHAR *buffer,T_S32 size)
{
T_S32 temp_size = size;
T_S32 size_counter = 0;
RAWDATA_LOG temp_rawDataStruct;
while(temp_size>0)
{
if(temp_size <= MAX_BUFFER_SIZE)
{
memcpy(temp_rawDataStruct.buffer,&buffer[size_counter],temp_size);
temp_rawDataStruct.buf_size = temp_size;
noofBytesWrittentoDeque+=temp_size;
}
else
{
memcpy(temp_rawDataStruct.buffer,&buffer[size_counter],sizeof(temp_rawDataStruct.buffer));
temp_rawDataStruct.buf_size = MAX_BUFFER_SIZE;
noofBytesWrittentoDeque+=MAX_BUFFER_SIZE;
}
CSingleLock datalock(&m_Cs_RawDataLog);
datalock.Lock();
m_RawdataLog.push_back(temp_rawDataStruct);
datalock.Unlock();
memset(&temp_rawDataStruct,0,sizeof(temp_rawDataStruct));
size_counter += MAX_BUFFER_SIZE;
temp_size = temp_size - MAX_BUFFER_SIZE;
}
}
unsigned int StartDataTransmitThread (LPVOID param)
{
RAWDATA_LOG temp_rawDataBuf;
int byesWritten=0;
CString tmpStr;
while(1)
{
if(!m_RawdataLog.empty())
{
CSingleLock datalock(&m_Cs_RawDataLog);
datalock.Lock();
temp_rawDataBuf = m_RawdataLog.front();
m_RawdataLog.pop_front();
datalock.Unlock();
//transmit the data through socket
byesWritten=WritetoClient(clientIp,clientPort,(const LPBYTE)&temp_rawDataBuf, MAX_BUFFER_SIZE);
noofBytesTransmitted+=byesWritten;
}
else
{
if(fileReadComplete == true)
{
break;
}
}
}
return true;
}
bool CreateServer(char ipaddr[],int port)
{
sockaddr_in ServerSockAddr;
WORD m_wVersionRequested;
WSADATA m_wsaData;
int m_wsaErr;
ServerSockAddr.sin_addr.s_addr=inet_addr("192.168.11.80");
ServerSockAddr.sin_family = AF_INET;
ServerSockAddr.sin_port = htons(2011);
m_wVersionRequested = MAKEWORD(2, 2);
m_wsaErr = WSAStartup(m_wVersionRequested, &m_wsaData);
if (m_wsaErr != 0)
{
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
MessageBox(L"WSAStartup failed with error:" + m_wsaErr);
return 1;
}
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (INVALID_SOCKET != sock)
{
if ( SOCKET_ERROR == bind(sock,(struct sockaddr *) & ServerSockAddr, sizeof(ServerSockAddr)))
{
int b= GetLastError();
closesocket( sock );
return false;
}
}
else
{
closesocket( sock );
return false;
}
m_hComm = (HANDLE) sock;
}
int WritetoClient(char ipaddr[],int port,BYTE buf[],int len)
{
sockaddr_in clientSockAddr;
int res=0;
SOCKET s = (SOCKET) m_hComm;
clientSockAddr.sin_addr.s_addr=inet_addr("192.168.11.80");
clientSockAddr.sin_family = AF_INET;
clientSockAddr.sin_port = htons(port);
res = sendto( s, (const char *)buf, len, 0, (SOCKADDR *) &clientSockAddr, sizeof(clientSockAddr));
return res;
}
#定义最大缓冲区大小1400
类型定义结构
{
缓冲区[最大缓冲区大小];
德沃德·布夫尺寸;
}原始数据记录;
deque m_RawdataLog;
无效传输连续()
{
if(m_sock_type_tcp==sock_UDP)
{
fileReadComplete=false;
//启动数据传输线程
pWin_thread=AfxBeginThread(StartDataTransmitThread,(LPVOID)this);
ReadFromFile();
}
}
void ReadFromFile()
{
int字节读取=0;
m_no_of_bytes=最大缓冲区大小;
字节输入\u buf[MAX\u BUFFER\u SIZE]={'\0'};
GetDlgItemText(IDEBC_文件名,m_文件输入);
m_InputFile=NULL;
/*打开要读取的文件*/
m_InputFile=_tfopen(m_fileInput,L“rb”);
if(m_InputFile==NULL)
{
AfxMessageBox(L“无法打开输入文件”);
}
其他的
{
而(!feof(m_InputFile))
{
bytesRead=fread(input_buf,1,m_no_字节,m_InputFile);
WRITERAWDATATOTODEQUE(输入字节,无字节);
noofbytes readfromfile+=字节读取;
}
fileReadComplete=true;
}
}
void writerawdatatodequence(T_UCHAR*缓冲区,T_S32大小)
{
T_S32温度_尺寸=尺寸;
T_S32尺寸_计数器=0;
RAWDATA_LOG temp_rawDataStruct;
同时(温度大小>0)
{
如果(temp_size我发现您的代码有几个问题
在服务器端,您将服务器的套接字绑定到192.168.11.80
,并将数据包发送到192.168.11.80
,而不是发送到WritetoClient()
函数的ipaddr
参数中指定的任何IP地址
在客户端,您正在将客户端的套接字绑定到服务器的IP地址
仅当客户端和服务器在同一台计算机上运行时,此设置才会工作。它不会在通过网络连接的多台计算机之间工作
您需要将客户端绑定到客户端自己机器的本地IP地址,而不是服务器的IP地址。并且您的服务器需要将数据包发送到客户端实际绑定到的IP地址
如果要确保客户端仅从服务器的IP地址接收数据,而不是从可能通过同一网络发送数据的其他计算机接收数据,可以选择将客户端的套接字连接到服务器的IP地址(是的,可以使用UDP的connect()
)
bind()
用于建立套接字的本地IP地址。connect()
用于建立套接字的远程/对等IP地址
因为您(可能)没有正确绑定客户端的套接字,和/或(可能)如果没有发送到正确的IP,您可能从其他地方接收到您不期望的数据。这可以解释您看到的巨大差异。我建议让您的客户输出其实际接收到的数据,以便您可以确保它接收到您期望的数据,例如:
n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &serveraddr, &serverlen);
if (n == SOCKET_ERROR)
{
int b = WSAGetLastError();
printf("ERROR in recvfrom\nError ID:%d\n",b);
}
else
{
BytesReceived += n;
TRACE("\nMessage Received from %s:%hu: '%.*s'", inet_ntoa(serveraddr.sin_addr), ntohs(serveraddr.sin_port), n, buf);
TRACE("\nTotal Bytes Received: %d\n", BytesReceived);
}
在每个块上调用inet\u addr
是浪费的…调用一次,保留结果,每次调用WriteToClient
时传递数值而不是字符串。我硬编码了IP地址和端口号,因为我在同一台PC上运行客户端和服务器。我希望客户端接收服务器发送的所有数据包。
n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &serveraddr, &serverlen);
if (n == SOCKET_ERROR)
{
int b = WSAGetLastError();
printf("ERROR in recvfrom\nError ID:%d\n",b);
}
else
{
BytesReceived += n;
TRACE("\nMessage Received from %s:%hu: '%.*s'", inet_ntoa(serveraddr.sin_addr), ntohs(serveraddr.sin_port), n, buf);
TRACE("\nTotal Bytes Received: %d\n", BytesReceived);
}