views:

51

answers:

2

Hey There,

I have the following problem:

I am starting WSA, then I am creating a UDP socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP) and try to recvfrom on this socket, but it always returns -1 and I get WSAEINVAL (10022)... I don´t know why?...

When I bind the port, that does not happen...

But it is very lame to bind the clients socket... (As far as I remember, i never had this problem before:/ )...

Anyone knows why this happens?...

(I am sending data to my server, which anwsers[ or at least, tries to^^])...

Inc::STATS CConnection::_RecvData(sockaddr* addr, std::string &strData)
{
    int ret, len, fromlen;      //return code / length of the data / sizeof(sockaddr)
    char *buffer;       //will hold the data
    char c;

    //recv length of the message
    fromlen = sizeof(sockaddr);
    ret = recvfrom(m_InSock, &c, 1, 0, addr, &fromlen);
    if(ret != 1)
    {
#ifdef __MYDEBUG__
        std::stringstream ss;
        ss << WSAGetLastError();
        MessageBox(NULL, ss.str().c_str(), "", MB_ICONERROR | MB_OK);
#endif
        return Inc::ERECV;
    }...

This is an working example i wrote a few moments ago, and it works, without the call to bind in the Client:

#pragma comment(lib, "Ws2_32.lib")

#define WIN32_LEAN_AND_MEAN

#include <WS2tcpip.h>
#include <Windows.h>
#include <iostream>

using namespace std;

int main()
{
    SOCKET sock;
    addrinfo* pAddr;
    addrinfo hints;
    sockaddr sAddr;
    int fromlen;
    const char czPort[] = "12345";
    const char czAddy[] = "incubbus.no-ip.info";

    WSADATA wsa;
    unsigned short usWSAVersion = MAKEWORD(2,2);

    char Buffer[22] = "TESTTESTTESTTESTTEST5";
    int ret;

    //Start WSA
    WSAStartup(usWSAVersion, &wsa);

    //Create Socket
    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    //Resolve host address
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_protocol = IPPROTO_UDP;
    hints.ai_socktype = SOCK_DGRAM;

    if(getaddrinfo(czAddy, czPort, &hints, &pAddr))
    {
        std::cerr << "Could not resolve address...\n";
        std::cin.get();
        return 1;
    }

    //Start Transmission
    while(1)
    {
        ret = sendto(sock, Buffer, sizeof(Buffer), 0, pAddr->ai_addr, pAddr->ai_addrlen);
        if(ret != sizeof(Buffer))
        {
            std::cerr << "Could not send data\n";
            std::cin.get();
            return 1;
        }

        fromlen = sizeof(SOCKADDR);
        ret = recvfrom(sock, Buffer, sizeof(Buffer), 0, &sAddr, &fromlen);
        if(ret != sizeof(Buffer))
        {
            std::cout << "Could not receive data -  error: " << WSAGetLastError() << std::endl;
            std::cin.get();
            return 1;
        }

        Buffer[ret-1] = '\0';
        std::cout << "Received: " << Buffer << std::endl;
    }
    return 0;
}
A: 

Here it says the following:

Parameters

s [in]: A descriptor identifying a bound socket.

...

Return Value

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.

As far as I remember bind is not required for a UDP socket because a bind call is made for you by the stack. I guess it's a Windows thing to require a bind on a socket used in a recvfrom call.

Eugen Constantin Dinca
Ye, i agree with You... I am wondering, why that is ,too... I never had to do it in the last windows-programms i made...
Incubbus
Can you post some code? Perhaps there's another parameter of recvfrom that's causing this.Ans also what version of Windows are you're using?
Eugen Constantin Dinca
Inc::STATS CConnection::_RecvData(sockaddr* addr, std::string strData){ int ret, len, fromlen; //return code / length of the data / sizeof(sockaddr) char *buffer; //will hold the data char c; //recv length of the message fromlen = sizeof(sockaddr); ret = recvfrom(m_InSock, if(ret != 1) {
Incubbus
erm--- how to make the code look like code, or isnt that possible in here?...
Incubbus
Add the code to your question to be able to properly format it.
Eugen Constantin Dinca
added the code above and added another working example i´ve written shortly, too...
Incubbus
+1  A: 

With UDP, you have to bind() the socket in the client because UDP is connectionless, so there is no other way for the stack to know which program to deliver datagrams to for a particular port.

If you could recvfrom() without bind(), you'd essentially be asking the stack to give your program all UDP datagrams sent to that computer. Since the stack delivers datagrams to only one program, this would break DNS, Windows' Network Neighborhood, network time sync....

You may have read somewhere on the net that binding in a client is lame, but that advice only applies to TCP connections.

Warren Young
Well... But I am creating a port, which I am receiving from.I am not telling the OS to send me a message , when anywhere on any port is any data... I am making a call to ask for it... Since I am able to grab all the data on the port, this should be sufficient, in my eyes
Incubbus
Without seeing your code, I can only guess, but I think you're putting the port number in the structure you pass for the "from" parameter. That doesn't help. That parameter isn't read by the stack, it is only written to, so your program can know who sent the datagram. Observe that it's optional, so you can pass 0 here, so again you're back to the same situation as before, where the stack has to have some way to know which program to deliver a datagram to based solely on the port number it came in on. That's what bind() does: it associates a program with a port.
Warren Young
http://codepad.org/4ZmoP4K5 <- this is the responsible code piece (I still don´t know how to show code in here , so i paste it on codepad)...the addr pointer points to an valid sockaddr*, and m_InSock was successfully initialized... (As I mentioned before, I already did send data that has been received...)But I am sure, that it should work for the client without the bind(), because i tried and example from a tutorial, which worked...
Incubbus
Nowhere in that code snippet is the UDP port number you want the stack to give you datagrams for. You need the bind() call to set up the association between the UDP port number and your program.
Warren Young
Hmmm... But why does it work without?...I wrote a small test client and an test server, to prove that the client can send and receive without bindig the socket...I posted the code above in an edit in my original post.I´m totally confused now :/...
Incubbus
Awww....I read the remarks section of the recvfrom function again and now all You wrote makes sense to me :D... sendto implicitly binds the socket...I´m sorry if I were a chunky student^^...Thank´s to both of You:)...
Incubbus
I wouldn't say that sendto() binds the socket, but it is true that you don't have to bind() to use sendto(). recvfrom() is different because of UDP's connectionless nature. In essence, a program using recvfrom() is a "server" even if you think of it as a client, because like a TCP server, a program that calls recvfrom() has to sit waiting for data from any possible sender.
Warren Young