[英]C++ winsock error
我有一个接受客户端的简单服务器。 客户端连接到服务器。 服务器要做的第一件事是:
这里的问题是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.