user980058
user980058

Reputation: 511

UDP test code not receiving messages (C++)

Firstly, please pardon the mess. I've been trying to modify example UDP code to work across windows/linux. There're probably a few blips of windows-specific code still laying around where I've been trying to figure out what on earth is going wrong.

This is my first time working with UDP instead of TCP.

If I uncomment the recvfrom stuff in the client, it blocks indefinitely IFF the the server is running. Otherwise it returns immediately, as expected. What I can't seem to figure out, is why my server, in its current state, can't seem to receive anything at all from the client.

What am I missing here?

Btw, I should also mention that if I bind the socket for the serverAddress from within the client and try to let it receive from itself (omitting the server altogether), it has no trouble doing so. (Also, I haven't tried this version on linux yet.)

Thanks

Server (receiver):

#ifdef _WIN32 || _WIN64 || _WINDOWS_
#include <WinSock2.h>
#pragma comment(lib, "Ws2_32.lib")
#define __COMPILE_FOR_WINDOWS__
#define SOCKET_INVALID(s) (s==INVALID_SOCKET)
#define SOCKET_TYPE SOCKET
#endif
#ifdef linux
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#define SOCKET_INVALID(s) (s<0)
#define SOCKET_TYPE int
#endif

#include <iostream>

#define BUFFER_LENGTH  1024

int main(int argc, char** argv)
{

#ifdef __COMPILE_FOR_WINDOWS__
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR)
    {
        std::cerr << "could not start up winsock-2.2\n";
        return 1;
    }
#endif 

    struct sockaddr_in serverAddress,
        clientAddress;
    unsigned short Port = 27015;
    char RecvBuf[BUFFER_LENGTH];

    SOCKET_TYPE socketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP/* or 0? */);
    if (SOCKET_INVALID(socketHandle))
    {
        std::cerr << "could not make socket\n";
        return 1;
    }

    memset(&serverAddress, 0, sizeof(serverAddress));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(Port);
    serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(socketHandle, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) != 0)
    {
        std::cerr << "could not bind socket\n";
        return 1;
    }

    int len;
    int client_addr_len;// = sizeof(clientAddress);
    while (1)
    {
        len = recvfrom(socketHandle,RecvBuf,BUFFER_LENGTH,0,(struct sockaddr*)&clientAddress,&client_addr_len);
        if (strncmp(RecvBuf,"END",3)==0) 
            break;
        if (len > 0)
        {
            //sendto(socketHandle, RecvBuf, len, 0, (struct sockaddr*)&clientAddress, sizeof(clientAddress));
            RecvBuf[len] = 0;
            std::cout << "received: " << RecvBuf << std::endl;
        }
    }

#ifdef __COMPILE_FOR_WINDOWS__
    closesocket(socketHandle);
    WSACleanup();
#endif
#ifdef linux
    close(socketHandle);
#endif
    std::cout<< "done\n";
    return 0;
}

#ifdef __COMPILE_FOR_WINDOWS__
#undef __COMPILE_FOR_WINDOWS__
#endif

#undef BUFFER_LENGTH
#undef SOCKET_INVALID

#ifdef SOCKET_TYPE
#undef SOCKET_TYPE
#endif

Client (sender):

#ifdef _WIN32 || _WIN64 || _WINDOWS_
#include <WinSock2.h>
#pragma comment(lib, "Ws2_32.lib")
#define __COMPILE_FOR_WINDOWS__
#define SOCKET_INVALID(s) (s==INVALID_SOCKET)
#define SOCKET_TYPE SOCKET
#endif
#ifdef linux
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#define SOCKET_INVALID(s) (s<0)
#define SOCKET_TYPE int
#endif

#include <iostream>

#define BUFFER_LENGTH  1024

int main(int argc, char** argv)
{

#ifdef __COMPILE_FOR_WINDOWS__
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR)
    {
        std::cerr << "could not start up winsock-2.2\n";
        return 1;
    }
#endif 

    struct sockaddr_in serverAddress,
        clientAddress;
    unsigned short Port = 27015;
    char msgBuf[BUFFER_LENGTH];

    SOCKET_TYPE socketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP/* or 0? */);
    if (SOCKET_INVALID(socketHandle))
    {
        std::cerr << "could not make socket\n";
        return 1;
    }

    //char address[512];
    //std::cout << "enter ip: ";
    //std::cin.getline(address, 512);

    memset(&serverAddress, 0, sizeof(serverAddress));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(Port);
    serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");

    int len;
    std::cout << "gimme something: ";
    std::cin.getline(msgBuf, BUFFER_LENGTH);

    while (1)
    {
        int n = sendto(socketHandle,msgBuf, strlen(msgBuf), 0,(struct sockaddr*)&serverAddress, sizeof(serverAddress));
        std::cout << "sent "<<n<<" bytes of the msg\n";
        /*len = recvfrom(socketHandle,msgBuf,BUFFER_LENGTH, 0, NULL, NULL);
        if (len > 0)
        {
            msgBuf[len] = 0;
            fputs(msgBuf, stdout);
        }else if(len < 0)std::cerr << "windowsy error\n";*/
    }

#ifdef __COMPILE_FOR_WINDOWS__
    closesocket(socketHandle);
    WSACleanup();
#endif
#ifdef linux
    close(socketHandle);
#endif
    std::cout << "done\n";
    return 0;
}

#ifdef __COMPILE_FOR_WINDOWS__
#undef __COMPILE_FOR_WINDOWS__
#endif

#undef BUFFER_LENGTH
#undef SOCKET_INVALID

#ifdef SOCKET_TYPE
#undef SOCKET_TYPE
#endif

Upvotes: 0

Views: 320

Answers (2)

user980058
user980058

Reputation: 511

Found the problem! I had to uncomment the part for client_addr_len=sizeof(clientAddress);.

For some reason, I thought that variable looked more like it was designed to receive a length for addresses of varying size from the recvfrom() function, so I doubted rather it really needed an initial value. This was the only way to make the datagrams start flying. :P

Also, to any future readers, the socklen_t issue can be quickly patched by adding

typedef int socklen_t;

to the windows specific section of the top directives, and changing the int len; to socklen_t len; - like Guntram said.

Upvotes: 0

Guntram Blohm
Guntram Blohm

Reputation: 9819

I didn't see any error, so i compiled both programs on my machine (openSuSE 11.3). Only thing i had to change was int client_addr_len to socklen_t client_addr_len Communication worked immediately. (Of course the client ran into the endless while(1) loop).

Are you doing this on one machine, or on 2? The client always sends to localhost, so 2 different machines won't work. Is there any firewall blocking communication?

Try to do a 'netstat -au | grep 27015' before and after starting the server. Is anything else listening on that socket before you start the server? Is the server listening after you start it?

Try to start the client and server with strace. Do you see any system call errors?

Upvotes: 1

Related Questions