我有一个接受客户端的简单服务器。 客户端连接到服务器。服务器将首先执行以下操作:
这里的问题是recv返回-1 WSAGetLastError返回WSAENOTSOCK :(非插件上的套接字操作。)Microsoft:“尝试对非套接字的操作进行操作。套接字句柄参数未引用有效套接字,或者对于select,fd_set的成员无效“。我无法弄清楚问题到底是什么。
客户端的套接字仍然有效,任何recv客户端剂量将立即返回
谢谢,Raxvan
答案 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()
中放置断点或调试打印,以了解我的意思。