C ++ winsock错误

时间:2010-06-21 12:34:46

标签: c++ winsock

我有一个接受客户端的简单服务器。 客户端连接到服务器。服务器将首先执行以下操作:

  1. 抓住客户端套接字
  2. 为客户
  3. 创建一个帖子
  4. call :: recv();
  5. 这里的问题是recv返回-1 WSAGetLastError返回WSAENOTSOCK :(非插件上的套接字操作。)Microsoft:“尝试对非套接字的操作进行操作。套接字句柄参数未引用有效套接字,或者对于select,fd_set的成员无效“。我无法弄清楚问题到底是什么。

    客户端的套接字仍然有效,任何recv客户端剂量将立即返回

    谢谢,Raxvan

5 个答案:

答案 0 :(得分:1)

我非常确定您只是立即关闭新接受的连接的套接字。

您使用sok类,它会自动关闭套接字(析构函数)。

sok client = listener.Accept();

以下代码从返回的套接字构造sok对象。它的生命周期受while循环的花括号的限制。 意思是 - 在创建一个应该从套接字读取的线程后立即关闭它。

P.S。 你滥用sok。根据它正在做的事情,你必须阻止为同一个套接字创建多个这样的对象。

例如,复制c'tor必须声明为私有。它在您的代码中是公开的。 另外,最好使用explicit关键字声明带有SOCKET的c'tor。

结论:考虑并检查您对sok课程的使用情况。

答案 1 :(得分:0)

According to MSDN,套接字出现问题。

  

尝试对非套接字的操作进行操作。套接字句柄参数未引用有效套接字,或者对于select,fd_set的成员无效。

你怎么'插'插座 - 你确定它有效吗?尝试检查::accept的回报。如果返回值== INVALID_SOCKET,那那就是你的问题。您可以致电WSAGetLastError尝试识别问题。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

请确保传递recv()函数正确的参数,包括正确的套接字id(无论如何它都是“unsigned int”)。

答案 4 :(得分:0)

好的,这很容易。

在您的代码中,您有

        inline sok  Accept()

按值返回sok

在此您将其分配给本地变量:

        sok client = listener.Accept();

并在此表达式的末尾,从Accept()返回的临时sok被销毁。您可能希望在sok::Close()中放置断点或调试打印,以了解我的意思。