Mar 09 2021 11:40 AM
I have some C code using winsock2 :
int fd = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
struct sockaddr_in sin = { ... };
if (fd == -1)
_ERR_( ... )
...
if ( bind ( fd, (struct sockaddr*)&sin, sizeof(struct sockaddr_in)) != 0 )
_ERR_( ... )
...
fd_set s_fds, s_e_fds;
UL_t
bytes_available=0;
register
U32_t s_n_fds = 0;
do
{ bytes_available=0;
FD_ZERO(&s_fds);
FD_SET(fd,&s_fds);
FD_ZERO(&s_e_fds);
FD_SET(fd,&s_e_fds);
struct timeval tv = { 0, 1000 };
s_n_fds = select( 1, &s_fds, NULL, &s_e_fds, &tv);
if (s_n_fds > 1)
_ERR_( ERROR_SYSTEM | ERROR_FATAL | ERROR_LOG
, ERR_ACT_RETURN, GetLastError() , 1 , "select failed"
);
else
if ( s_n_fds == 1 )
{ if ( FD_ISSET( fd, &s_fds ) )
{more_bytes:
r = ioctlsocket( fd, FIONREAD, &bytes_available );
if ( r != 0 )
_ERR_( ERROR_SYSTEM | ERROR_FATAL | ERROR_LOG
, ERR_ACT_RETURN, GetLastError(), 1, "ioctlsocket failed"
);
say("RD: %u",bytes_available);
if( bytes_available > 4)
{ struct sockaddr_in snsin={0};
U32_t sin_len = sizeof(struct sockaddr_in);
r = recvfrom((SOCKET) fd, (char*) &_iob_.b[0], bytes_available, MSG_WAITALL,
(struct sockaddr*)&snsin, &sin_len );
say("RCV: %u %u WSAE: %u",fd,r,WSAGetLastError());
if ( r < 0 )
_ERR_(...);
....
} while (fd != -1 ) ;
The above code prints:
$ .\${MY_EXE}
${MY_EXE}[9692]: RD: 121.
${MY_EXE}[9692]: RCV: 440 4294967295 WSAE: 10045.
src\logio.exe[9692] : logio.c:115@(main) : Error: 10045:'The attempted operation is not supported for the type of object referenced.
' - recv failed.
So, for the bound UDP socket 'fd', the select() succeeded, the ioctlsocket() succeeded, returning
a 'bytes_available' of 121 bytes, but any attempt to then call either 'recv' or 'recvfrom' with that 'fd'
socket then returns SOCKET_ERROR with extended error code 10045, 'Operation Not Supported'.
Please, can anyone enlighten me what the 'Supported' way of reading a UDP packet is on Windows, if neither winsock2's 'recv' nor its 'recvfrom' can be used ? I would like to know the sender's address,
so was using 'recvfrom' . What method am I meant to be using to receive a single packet from a bound UDP
socket , and the address it was sent from ?
Mar 09 2021 12:18 PM
Mar 09 2021 12:59 PM
Mar 09 2021 01:07 PM
/*
Simple UDP Server
*/
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define BUFLEN 512 //Max length of buffer
#define PORT 8888 //The port on which to listen for incoming data
int main()
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen , recv_len;
char buf[BUFLEN];
WSADATA wsa;
slen = sizeof(si_other) ;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_port = htons( 60514 );
server.sin_addr.s_addr =htonl((127<<24)|1);
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//keep listening for data
unsigned int bytes_available = 0;
while(1)
{
printf("Waiting for data...");
fflush(stdout);
//clear the buffer by filling null, it might have previously received data
memset(buf,'\0', BUFLEN);
bytes_available = 0;
if ( ioctlsocket(s, FIONREAD, &bytes_available) != 0 )
{
printf("ioctlsocket() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
if ( bytes_available > 0 )
{
//try to receive some data, this is a blocking call
if ((recv_len = recvfrom(s, buf, bytes_available, MSG_WAITALL, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
printf("Data: %s\n" , buf);
}else
Sleep(1000);
}
closesocket(s);
WSACleanup();
return 0;
}
Mar 09 2021 01:11 PM