1
votes

Hai friends I am a newbie learning winsock2. the following is my udp server and client programs.

I this program the client does not know the ip address of the server but knows only the port. But the server broadcasts a message all over the network.

when the client gets the message it traces back the ip of the server and connects to it.

Both my server and client show no error while compiling.

But while Executing the client's recvfrom() statement shows error the following are the part of my code.

SERVER CODE:

#include "stdafx.h"
#include<stdio.h>
#include<WinSock2.h>
#pragma comment (lib,"ws2_32.lib")

DWORD WINAPI UDPCONN(LPVOID x)
{
    SOCKET s=(SOCKET)x;
    char bro[200]="I am SERVER";
    struct sockaddr_in hum;
    hum.sin_family=AF_INET;
    hum.sin_addr.s_addr=INADDR_BROADCAST;
    hum.sin_port=htons(8888);
    while (1)
    {
        if(sendto(s,bro,sizeof(bro),0,(struct sockaddr *)&hum,sizeof(hum))==SOCKET_ERROR)
        {
            printf("\nBroadcast failed ERROR CODE : %d\n",WSAGetLastError());
            exit(1);
        }
    }
 }

int _tmain(int argc, _TCHAR* argv[])
{
    SOCKET s;
    struct sockaddr_in hum;
    int opt=1;

    //Initializing winsock2
    WSADATA wsa;
    if((WSAStartup(MAKEWORD(2,2),&wsa))!=0)
    {
        printf("\nWinsock Not initialized ERROR CODE : %d\n",WSAGetLastError());
        return 1;
    }

    //UDP Socket Creation
    if((s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==INVALID_SOCKET)
    {
        printf("\nUDP Socket not created ERROR CODE : %d\n",WSAGetLastError());
        WSACleanup();
        return 1;
    }

    //socket defenition
    hum.sin_family=AF_INET;
    hum.sin_addr.s_addr=INADDR_ANY;
    hum.sin_port=htons(8888);

    //Broadcast permission
    if((setsockopt(s,SOL_SOCKET,SO_BROADCAST,(char *)&opt,sizeof(opt)))<0)
    {
        printf("\nBroadcast permissions failed ERROR CODE : %d\n",WSAGetLastError());
        WSACleanup();
        return 1;
    }

    //UDP SOCKET Binding 
    if((bind(s,(sockaddr *)&hum,sizeof(hum)))==SOCKET_ERROR)
    {
        printf("\nUDP socket binding failed ERROR CODE :%d\n",WSAGetLastError());
        WSACleanup();
        return 1;
    }

    //UDP connection thread
    DWORD th;
    CreateThread(NULL,0,UDPCONN,(LPVOID)s,0,&th);

CLIENT CODE :

#include "stdafx.h"
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
    //UDP Data
    int slen;
    char message[300];
    int opt=1;
    SOCKET s;
    struct sockaddr_in sent;

    //Initializing winsock
    WSADATA wsa;
    if((WSAStartup(MAKEWORD(2,2),&wsa))!=0)
    {
        printf("\nFailed Initializing Winsock EROR CODE : %d\n",WSAGetLastError());
        return 1;
    }

    //UDP Socket creation
    if((s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))== SOCKET_ERROR)
    {
        printf("\nUDP socket creation failed ERROR CODE :%d\n",WSAGetLastError());
        WSACleanup();
        return 1;
    }

    //UDP Broadcast permissions
    if((setsockopt(s,SOL_SOCKET,SO_BROADCAST,(char *)&opt,sizeof(opt)))<0)
    {
        printf("\nERROR in broadcasting ERROR CODE : %d \n",WSAGetLastError());
        WSACleanup();
        return 1;
    }

    //UDP socket definition
    sent.sin_family=AF_INET;
    sent.sin_addr.s_addr=INADDR_ANY;
    sent.sin_port=htons(8888);

    //UDP Receiving broadcasted data
    slen=sizeof(sent);
    //fflush(stdout);
    memset(message,'\0',300);
    if((recvfrom(s,message,sizeof(message),0,(struct sockaddr *)&sent,&slen))<0)
    {
        printf("\nUDP Broadcast not received ERROR CODE : %d\n",WSAGetLastError());
        WSACleanup();
        return 1;
    }
    puts("\nGot server broadcast\n");
    puts("\nTracing server ip\n");
    getpeername(s,(sockaddr *)&sent,&slen);

    ...
}

Here my client throw an error

UDP Broadcast not received ERROR CODE : 10022

Description of the error code 10022 : Invalid argument.

Some invalid argument was supplied (for example, specifying an invalid level to the setsockopt function). In some instances, it also refers to the current state of the socket—for instance, calling accept on a socket that is not listening.

According to the error description one of the arguments in the recvfrom() function is invalid. But i could not find out the invalid argument .

Please help me clear the error.

2
this is the syntax for the setsockopt() function: int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); which is not what is being passed as the 5th parameter to setsockoptuser3629249

2 Answers

3
votes

If you read the recvfrom() documentation, it tells you exactly why you are getting the error in your client code:

Parameters

s [in]
A descriptor identifying a bound socket.

...

WSAEINVAL
The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled, or (for byte stream-style sockets only) len was zero or negative.

You are not calling bind() on the socket before calling recvfrom(). More importantly, you cannot bind() the client and server to the same IP/port when they are running on the same machine. Change the port that you broadcast to, and then have the client bind to that port.

Also, the last two parameters of recvfrom() provide you with the IP/Port of the datagram sender. They are not for specifying the network adapter to read datagrams on. You do not need to use getpeername() in this situation.

There are some other issues with your code:

On the client side, socket() returns INVALID_SOCKET on failure, not SOCKET_ERROR.

On the server side, you really should not be using INADDR_BROADCAST. You should bind() the server socket to a specific network adapter and then sendto() its particular subnet broadcast IP, which you can calculate using GetAdaptersInfo() or GetAdaptersAddresses().

And on both sides, you cannot use WSAGetLastError() if WSAStartup() fails, that is why WSAStartup() returns the error code directly. And you are not closing the sockets before calling WSACleanup();

Try this:

SERVER CODE:

#include "stdafx.h"
#include <stdio.h>
#include <WinSock2.h>
#pragma comment (lib,"ws2_32.lib")

DWORD WINAPI UDPCONN(LPVOID x)
{
    SOCKET s = (SOCKET)x;
    char bro[200] = "I am SERVER";
    struct sockaddr_in hum;

    memset(&hum, 0, sizeof(addr));
    hum.sin_family = AF_INET;
    hum.sin_addr.s_addr = INADDR_BROADCAST; // TODO: replace with subnet broadcast IP
    hum.sin_port = htons(8887);

    while (1)
    {
        if (sendto(s, bro, sizeof(bro), 0, (struct sockaddr *)&hum, sizeof(hum)) == SOCKET_ERROR)
        {
            printf("\nBroadcast failed ERROR CODE : %d\n", WSAGetLastError());
            return 1;
        }
    }

    return 0;
 }

int _tmain(int argc, _TCHAR* argv[])
{
    SOCKET s;
    struct sockaddr_in hum;
    int err, opt=1;

    //Initializing winsock2
    WSADATA wsa;
    err = WSAStartup(MAKEWORD(2,2), &wsa);
    if (err != 0)
    {
        printf("\nWinsock Not initialized ERROR CODE : %d\n", err);
        return 1;
    }

    //UDP Socket Creation
    s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (s == INVALID_SOCKET)
    {
        printf("\nUDP Socket not created ERROR CODE : %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    //socket defenition
    memset(&hum, 0, sizeof(hum));
    hum.sin_family = AF_INET;
    hum.sin_addr.s_addr = INADDR_ANY; // TODO: replace with a specific NIC IP
    hum.sin_port = htons(8888);

    //Broadcast permission
    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt)) == SOCKET_ERROR)
    {
        printf("\nBroadcast permissions failed ERROR CODE : %d\n", WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return 1;
    }

    //UDP SOCKET Binding 
    if (bind(s, (sockaddr *)&hum, sizeof(hum)) == SOCKET_ERROR)
    {
        printf("\nUDP socket binding failed ERROR CODE : %d\n", WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return 1;
    }

    //UDP connection thread
    DWORD th;
    HANDLE hThread = CreateThread(NULL,0, UDPCONN, s, 0, &th);
    if (!hThread)
    {
        printf("\nUDP thread failed ERROR CODE : %u\n", GetLastError());
        closesocket(s);
        WSACleanup();
        return 1;
    }

    // do other things, wait for thread to terminate ...

    DWORD exitCode = 0;
    GetExitCodeThread(hThread, &exitCode);
    CloseHandle(hThread);

    closesocket(s);
    WSACleanup();

    return exitCode;
}

CLIENT CODE :

#include "stdafx.h"
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
    //UDP Data
    int addrlen, msglen;
    char message[300];
    int err, opt=1;
    SOCKET s;
    struct sockaddr_in hum, addr;

    //Initializing winsock
    WSADATA wsa;
    err = WSAStartup(MAKEWORD(2,2), &wsa);
    if (err != 0)
    {
        printf("\nFailed Initializing Winsock EROR CODE : %d\n", err);
        return 1;
    }

    //UDP Socket creation
    s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (s == INVALID_SOCKET)
    {
        printf("\nUDP socket creation failed ERROR CODE : %d\n", WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return 1;
    }

    //UDP Broadcast permissions
    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt)) == SOCKET_ERROR)
    {
        printf("\nERROR in broadcasting ERROR CODE : %d \n", WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return 1;
    }

    //UDP socket definition
    memset(&hum, 0, sizeof(addr));
    hum.sin_family = AF_INET;
    hum.sin_addr.s_addr = INADDR_ANY;
    hum.sin_port = htons(8887);

    //UDP SOCKET Binding 
    if (bind(s, (sockaddr *)&hum, sizeof(hum)) == SOCKET_ERROR)
    {
        printf("\nUDP socket binding failed ERROR CODE : %d\n", WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return 1;
    }

    //UDP Receiving broadcasted data
    addrlen = sizeof(addr);
    msglen = recvfrom(s, message, sizeof(message), 0, (struct sockaddr *)&addr, &addrlen);
    if (msglen == SOCKET_ERROR)
    {
        printf("\nUDP Broadcast not received ERROR CODE : %d\n", WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return 1;
    }

    printf("\nGot server broadcast\n");
    printf("\nServer ip: %s, port: %hu\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
    printf("\nMessage: %.*s\n", msglen, message);

    ...
}
-1
votes

Whatever method i tried sending a broadcast from server and receiving the broadcast from client is not working efficiently.

Instead i done the reverse i.e send a broadcast from client to search for the server is working perfectly.

Here is my modified code.

SERVER CODE:

#include "stdafx.h"
#include<stdio.h>
#include<WinSock2.h>
#pragma comment (lib,"ws2_32.lib")

DWORD WINAPI UDPCONN(LPVOID x)
{

SOCKET s=(SOCKET)x;
struct sockaddr_in server;
int len;
char buf[500]=("I am server");

char message[500];
len=sizeof(server);

int opt=1;

if((s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==INVALID_SOCKET)
{
    printf("\nSocket creation failed. ERROR CODE : %d\n",WSAGetLastError());
    WSACleanup();
    ExitThread(NULL);
}

server.sin_family=AF_INET;
server.sin_addr.s_addr=INADDR_ANY;
server.sin_port=htons(8888);

if(setsockopt(s,SOL_SOCKET,SO_BROADCAST,(char *)&opt,sizeof(opt))<0)
{
    printf("\nSetting broadcast failed : %d\n",WSAGetLastError());
    WSACleanup();
    ExitThread(NULL);
}
if((bind(s,(sockaddr *)&server,sizeof(server)))==SOCKET_ERROR)
{
    printf("\nBind failed. ERROR CODE : %d\n",WSAGetLastError());
    WSACleanup();
    ExitThread(NULL);
}

while(1)
{

    fflush(stdout);
     memset(message,'\0', 500);
    //try to receive some data, this is a blocking call
    if (recvfrom(s, message, 500, 0, (struct sockaddr *) &server,&len) == SOCKET_ERROR)
    {
        printf("recvfrom() failed with error code : %d" , WSAGetLastError());
        ExitThread(NULL);
    }

    if(sendto(s,buf,sizeof(buf),0,(struct sockaddr *)&server,sizeof(server))==SOCKET_ERROR)
    {
        printf("\nIP Broadcast failed ERROR code : %d\n",WSAGetLastError());
        WSACleanup();
        ExitThread(NULL);
    }
 }

}
int _tmain(int argc, _TCHAR* argv[])
{
SOCKET s;
//struct sockaddr_in hum;
int opt=1;
//Initializing winsock2
WSADATA wsa;
if((WSAStartup(MAKEWORD(2,2),&wsa))!=0)
{
    printf("\nWinsock Not initialized ERROR CODE : %d\n",WSAGetLastError());
    return 1;
}
s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);

//UDP connection thread
DWORD th;
CreateThread(NULL,0,UDPCONN,(LPVOID)s,0,&th);
closesocket(s);

CLIENT CODE :

#include "stdafx.h"
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
//UDP Data
int slen;
char message[600];
char buf[300]=("Hai server");
int opt=1;
SOCKET s;
struct sockaddr_in sent;

//TCP Connection data
SOCKET t;
struct sockaddr_in server;
char messag[300],server_reply[300];
int recv_size;


//Initializing winsock
WSADATA wsa;
if((WSAStartup(MAKEWORD(2,2),&wsa))!=0)
{
    printf("\nFailed Initializing Winsock EROR CODE : %d\n",WSAGetLastError());
    return 1;
}

//UDP Socket creation
if((s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))== INVALID_SOCKET)
{
    printf("\nUDP socket creation failed ERROR CODE :%d\n",WSAGetLastError());
    WSACleanup();
    return 1;
}

//UDP Broadcast permissions
if((setsockopt(s,SOL_SOCKET,SO_BROADCAST,(char *)&opt,sizeof(opt)))<0)
    {
        printf("\nERROR in broadcasting ERROR CODE : %d \n",WSAGetLastError());
        WSACleanup();
        return 1;
    }

//UDP socket definition
sent.sin_family=AF_INET;
sent.sin_addr.s_addr=INADDR_BROADCAST;
sent.sin_port=htons(8888);

if (sendto(s, buf, sizeof(buf) , 0 , (struct sockaddr *) &sent,sizeof(sent)) == SOCKET_ERROR)
    {
        printf("sendto() failed with error code : %d" , WSAGetLastError());
        exit(EXIT_FAILURE);
    }

//UDP Receiving broadcasted data
slen=sizeof(sent);
fflush(stdout);
memset(message,'\0',300);
if((recvfrom(s,message,sizeof(message),0,(struct sockaddr *)&sent,&slen))<0)
{
    printf("\nUDP Broadcast not received ERROR CODE : %d\n",WSAGetLastError());
    WSACleanup();
    return 1;
}
puts("\nGot server broadcast\n");
puts("\nTracing server ip\n");
getpeername(s,(sockaddr *)&sent,&slen);
closesocket(s);

Both the codes here works perfectly fine in visual studios 2012. Also this is just one part of my whole big program. But still this part works perfectly fine independently.

So please make sure you compiled and run the program before posting negative comments.