I've got a test program (see code below) that sends and receives 1400 bytes using UDP. The first time through the while loop, the timeout will occur, causing the buffer to be sent. During the subsequent wait, the socket should become "readable," causing the buffer to be received. This looping construct will continue until I kill the program.
The problem I am encountering is that this bit of code does not work uniformly across Win2K/XP machines for packets above 1272 bytes. I've got 2 Win2k machines and 1 XP machine that it seems to work on regardless of packet size. However, I've got 3 XP machines that it works on so long as the packet size is less than or equal to 1272. Any ideas? Does this have anything to do with the UDP MTU? I've seen info online that would indicate that adjusting the MTU settings in the registry might fix this, but there's been nothing definitive. In the end, I have an application that needs to be able to send packets of up to 1400 bytes without fragmentation.
/********************
** TEST PROGRAM
********************/
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <memory.h>
#include <stdio.h>
void main ()
{
// Get the size of the buffer from the user.
int size = 0;
::printf("Enter the size of the send/receive buffer:\n");
::scanf("%ld", &size);
char *sendbuf = new char[size];
char *recvbuf = new char[size];
// Initialize the Winsock DLL.
WORD versionRequested = MAKEWORD(2,2);
WSADATA wsadata;
::WSAStartup(versionReques
ted, &wsadata);
// Create the socket.
SOCKET s = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
// Set the socket for broadcast and non-blocking mode.
unsigned long on = 1;
::setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char const *)&on, sizeof(on));
::ioctlsocket(s, FIONBIO, &on);
// Bind the socket.
unsigned short port = 3000;
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_port = ::htons(port);
addr.sin_addr.s_addr = ::htonl(INADDR_ANY);
::bind(s, (PSOCKADDR)&addr, sizeof(addr));
// Create the 'readable' socket event.
WSAEVENT wsaevent = ::WSACreateEvent();
::WSAEventSelect(s, wsaevent, FD_READ);
// Primary loop
while (true) {
switch (::WSAWaitForMultipleEvent
s(1, &wsaevent, false, 1000, false)) {
case WSA_WAIT_EVENT_0:
{
WSANETWORKEVENTS wsaNetworkEvents;
::WSAEnumNetworkEvents(s, wsaevent, &wsaNetworkEvents);
if (wsaNetworkEvents.lNetwork
Events & FD_READ) {
int bytesRemaining = size, bytesRecv = 0, ix = 0;
// Receive the buffer.
while (bytesRemaining > 0) {
bytesRecv = ::recvfrom(s, &recvbuf[ix], bytesRemaining, 0, 0, 0);
if (bytesRecv == SOCKET_ERROR) {
if (::WSAGetLastError() != WSAEWOULDBLOCK) {
throw;
}
break;
}
bytesRemaining -=bytesRecv;
ix += bytesRecv;
}
::printf("Received %ld bytes...\n", ix);
}
break;
}
case WSA_WAIT_TIMEOUT:
{
// Send 1400 'G' characters on the socket. 'G' is arbitrary.
::memset(sendbuf, 'G', size);
SOCKADDR_IN dest;
dest.sin_family = AF_INET;
dest.sin_port = ::htons(port);
dest.sin_addr.s_addr = ::htonl(INADDR_BROADCAST);
::sendto(s, sendbuf, size, 0,
(SOCKADDR *)&dest, sizeof(dest));
::printf("Sent %ld bytes...\n", size);
break;
}
default:
throw;
}
}
::closesocket(s);
::WSACleanup();
delete [] sendbuf;
delete [] recvbuf;
return;
}
Start Free Trial