tags:

views:

146

answers:

5
+1  Q: 

C++ winsock error

Hello , 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

A: 

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.

Jon Cage
yea it is i call WSAGetLastError just after accept and there are no error. The returned socket from accept() is valid
Raxvan
yes it is a valid value, different from INVALID_SOCKET.accept() dose not fail in any way.
Raxvan
A: 
    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);/**/
}
Raxvan
the member com_stream in the client is of type tcpStream.tcpSteam is just wrappe around the socket for reading and writing
Raxvan
A: 

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

Poni
+1  A: 

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.

valdo
A: 

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.

atzz
yea , you are right.... god i diden't figured that out, Thanks
Raxvan