Raxvan
Raxvan

Reputation: 13

C++ winsock error

i have a simple server that accepts clients. The client connect to the server. The first thing the server will do the following:

  1. grab the client socket
  2. create a thread for client
  3. call ::recv();

the problem here is that recv returnes -1 WSAGetLastError returnes WSAENOTSOCK: (Socket operation on nonsocket.) Microsoft: "An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid." i can't really figure out what the problem really is.

the client has the socket still valid , and any recv the client dose will instantly return

Thanks, Raxvan

Upvotes: 1

Views: 860

Answers (5)

atzz
atzz

Reputation: 18010

OK, that's easy.

In your code, you have

        inline sok  Accept()

that returns a sok by value.

Here you assign it to a local variable:

        sok client = listener.Accept();

and at the end of this expression, the temporary sok returned from Accept() gets destroyed. You might want to put a breakpoint or a debug print in sok::Close() to see what I mean with your own eyes.

Upvotes: 0

valdo
valdo

Reputation: 12943

I'm pretty much sure that you just immediately close the socket of the newly accepted connection.

You make use of the sok class, which closes the socket automatically at its d'tor (destructor).

sok client = listener.Accept();

The following code constructs the sok object from the returned socket. Its lifetime is bounded by the curly braces of the while loop. Means - immediately after creating a thread that is supposed to read from the socket- you close it.

P.S. You misuse the sok. According to what it's doing you must prevent creation of more than one such an object for the same socket.

For instance the copy c'tor must be declared private. And it's public at your code. Also it's a good idea to declare the c'tor that takes a SOCKET with explicit keyword.

Conclusion: think and review your usage of sok class.

Upvotes: 1

Poni
Poni

Reputation: 11317

Just make sure you pass the recv() function the correct parameters, INCLUDING the correct socket's id (it's an "unsigned int" anyway!).

Upvotes: 0

Raxvan
Raxvan

Reputation: 13

    void NetworkServer::RunServer()//main server loop
    {
        while (flags & server_running)
        {
            sok client = listener.Accept();
            if (listener && client.IsValid())
            {
                if (clients.size >= MaxClients)
                {
                    client.Close();
                    continue;
                }
                ClientHandler* h = constructor->ConstructClient();
//ConstructClient() is just doing "new ClientHandler()";
                h->com_stream.forceConnected(client);
                h->id = client_ids.getId();
                h->flags = client_active;
                h->server = this;
                this->HandleNewConnection(h);//nothing..

                locker.Enter();
                clients.add(h);//add client to the client array
                h->threadRun();//stars the thread

                locker.Leave();
            }
            else
            {
                break;
            }
        }
    }


    void tcpStream::forceConnected(sok& ss)
    {
        server.socket = ss.socket;
        connected = true;
    }



class sok
    {
    private:
        SOCKET      socket;
    public:
        inline      sok()
            : socket(INVALID_SOCKET)
        {
        }
        inline      sok(SOCKET s)
            : socket(s)
        {
        }
        inline      sok(const sok & s)
            : socket(s.socket)
        {
        }
        inline      operator bool()const
        {
            return (socket != INVALID_SOCKET);
        }
        inline      ~sok()
        {
            Close();
        }
        inline bool IsValid()const
        {
            return (socket != INVALID_SOCKET);
        }
        inline void operator = (const sok & s)
        {
            socket = s.socket;
        }
    public:
        inline void Close()
        {
            if (socket != INVALID_SOCKET)
            {
                closesocket(socket);
                socket = INVALID_SOCKET;
            }
        }
        inline sok  Accept()
        {
            return sok(::accept(socket, 0, 0));
        }
        bool        tcpClient(NetAddress& adr);
        bool        tcpServer(wtf::ushort port, wtf::u32 clients = 10);
    private:
        friend class tcpStream;
    };

uint tcpStream::read(void* out, const uint size)
{
    wtf::n32 r = ::recv(server.socket, (char*)out, size, 0);//this failes
    //int e = WSAGetLastError();
    connected = ((r) != (-1));
    return ((uint)r);/**/
}

Upvotes: 0

Jon Cage
Jon Cage

Reputation: 37458

According to MSDN, there was a problem with the socket.

An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid.

How did you 'grub' the socket - are you sure it's valid? Try checking the return from ::accept. If the return value == INVALID_SOCKET, then that's your problem. You can call WSAGetLastError to try and identify the problem then.

Upvotes: 0

Related Questions