繁体   English   中英

C ++ Winsock错误

[英]C++ winsock error

我有一个接受客户端的简单服务器。 客户端连接到服务器。 服务器要做的第一件事是:

  1. 抓住客户端套接字
  2. 为客户端创建线程
  3. 调用:: recv();

这里的问题是recv返回-1。WSAGetLastError返回WSAENOTSOCK :(对非套接字的套接字操作。)Microsoft:“试图对非套接字的对象进行了操作。套接字句柄参数未引用有效的套接字,或者用于select ,则fd_set的成员无效。” 我真的不能弄清楚问题出在哪里。

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

谢谢,拉克斯万

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

您可以使用sok类,该类会在其d'tor(析构函数)处自动关闭套接字。

sok client = listener.Accept();

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

PS:您滥用了sok 根据操作,您必须防止为同一套接字创建多个这样的对象。

例如,副本c'tor必须声明为私有。 并且在您的代码中是公开的。 同样,最好声明一个带有explicit关键字的SOCKET的c'tor。

结论:思考并回顾您对sok类的用法。

根据MSDN的说法 ,套接字存在问题。

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

您如何“抓紧”插座-您确定插座有效吗? 尝试检查::accept的返回值。 如果返回值== INVALID_SOCKET,那就是您的问题。 您可以调用WSAGetLastError尝试然后找出问题。

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

只要确保您为recv()函数传递了正确的参数,包括正确的套接字ID(无论如何,它就是“ unsigned int”!)。

好,很简单。

在您的代码中,您有

        inline sok  Accept()

按值返回sok

在这里,您将其分配给局部变量:

        sok client = listener.Accept();

在此表达式的末尾,从Accept()返回的临时sok被销毁。 您可能想在sok::Close()放置一个断点或调试打印,以便亲眼看到我的意思。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM