开发者

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


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.


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.


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.


    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);/**/
}


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜