user2521521
user2521521

Reputation: 3

C++ UDP recvfrom is acting strange, WSAGetLastError = 10014

My code is behaving very strange on Windows, but working on Linux... This is my server.cpp:

#include <cstdio>
#include "packet.h"
#include "socket.h"

int main(int argc, char *argv[])
{
Socket s;

s.bindAt(1337);
for (int i = 0; i < 20; i++) {
    Packet p;
    int32_t a;
    char *b;

    int abc = s.receive();
    printf("abc = %d\n", abc);
    printf("error = %d\n", WSAGetLastError());
    p.getInt(&a);
    p.getString(&b);

    printf("int = %d\nstring = %s\n", a, b);
    delete[] b;
}

return 0;
}

and here is the socket.cpp:

Socket::Socket()
{
#ifdef _WIN32
WSADATA wsa;
if (sockNum == 0 && WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    throw 1;
#endif

sock = socket(AF_INET, SOCK_DGRAM, 0);
#ifdef _WIN32
if (sock == INVALID_SOCKET)
#else
if (sock == -1)
#endif
    throw 2;

addrlen = 0;
sockNum++;
}


int Socket::bindAt(unsigned short port)
{
struct sockaddr_in sa = { 0 };
memset(&sa, 0, sizeof(sa));

sa.sin_family = AF_INET;
sa.sin_port = htons(port);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
return bind(sock, (struct sockaddr *) &sa, sizeof(sa));
}

ssize_t Socket::receive()
{
ssize_t n;

#ifdef _WIN32

char msg[100];
n = recvfrom(sock,msg, sizeof(msg), 0,(SOCKADDR*) &addr, &addrlen);
#else
n = recvfrom(sock, p->buf, p->bufSize, 0,
        (struct sockaddr *) &addr, &addrlen);
#endif
/*if (n < 0)
    p->bufSize = 0;
else
    p->bufSize = n;*/
return n;
}

and basically the header of it:

typedef SOCKET socket_t;
typedef int ssize_t;

class Socket
{
public:
socket_t sock;
socklen_t addrlen;
struct sockaddr_in addr;

Socket();
~Socket();

int connect(const char *ip, unsigned short port);
int bindAt(unsigned short port);
ssize_t send(Packet *p);
ssize_t receive();
};

If I change the last 2 parameters of the recvfrom, the (SOCKADDR*) &addr, and &addrlen to NULL it works, but what is wrong with these 2 parameters?

Upvotes: 0

Views: 2805

Answers (2)

Philip Stuyck
Philip Stuyck

Reputation: 7447

instead of this :

addrlen = 0;

do this:

addrlen = sizeof(sockaddr_in)

it should work, because you are identifying correctly the size of the output address buffer pointer.

Upvotes: 4

Barmar
Barmar

Reputation: 780663

From MSDN description of WSAEFAULT (10014):

The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a sockaddr structure, is smaller than the sizeof(sockaddr).

So if you supply an uninitialized value of addrlen, it may be too small, and result in this error.

If addr is NULL, it means you don't want the address filled in, so addrlen is ignored.

Upvotes: 2

Related Questions