C++ winsock错误
我有一个接受客户端的简单服务器。 客户端连接到服务器。服务器将执行以下操作的第一件事:C++ winsock错误
- 抢客户socket
- 创建一个线程为客户
- 电话::的recv();
这里的问题是,recv的returnes -1 WSAGetLastError returnes WSAENOTSOCK:(。上nonsocket插座操作)微软:“一个操作尝试的东西,不是一个套接字无论是套接字句柄参数没有引用一个有效的套接字,或者select,fd_set的成员无效。“我无法弄清楚问题究竟在哪里。
客户有插座仍然有效,任何recv的客户量会立即返回
感谢,Raxvan
好吧,那很简单。
在代码中,你有
inline sok Accept()
按值返回sok
。
在这里,您将其分配到一个局部变量:
sok client = listener.Accept();
,并在此表达的结束,从接受返回临时sok
()被销毁。您可能需要在sok::Close()
中放置断点或调试打印以查看我的意思。
是啊,你是正确的....上帝,我想通diden't说出来,谢谢 – Raxvan 2010-06-21 18:37:55
According to MSDN,有一个与插座有问题。
一个操作尝试在不是套接字的东西上。套接字句柄参数没有引用有效的套接字,或者对于select,fd_set的成员无效。
你是怎么'grub'的插口 - 你确定它是有效的吗?尝试检查从::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);/**/
}
客户端中的成员com_stream是tcpStream类型的。 tcpSteam只是wrappe插座周围读写 – Raxvan 2010-06-21 13:23:48
只要确保您通过recv()函数正确的参数,包括正确的套接字的ID(无论如何这是一个“无符号整数”)。
我很肯定你只是立即关闭新接受的连接的套接字。
您可以使用sok
类,该类在其终端(析构函数)处自动关闭套接字。
sok client = listener.Accept();
以下代码从返回的套接字构造sok
对象。它的生命周期由while
循环的花括号限制。 意味着 - 创建一个应该从套接字读取的线程后立即关闭它。
P.S. 您误用sok
。根据它在做什么必须防止为同一套接字创建多个这样的对象。
例如复制c'tor必须声明为私人。它在您的代码中公开。 另外它是一个好主意,宣布c'tor需要与explicit
关键字SOCKET。
结论:考虑并检查您的sok
类的用法。
任何机会,你可以张贴一些示例代码?这会让我们更容易进行调试。我猜grub应该是'抢'? – 2010-06-21 12:43:26
它是最基本的服务器 SOCKER s = :: accept(lsock,0,0); Cient * c =新客户; C-> RunThread(); //这里的线程将被创建并启动 – Raxvan 2010-06-21 12:45:32
您是否尝试过这样做没有穿了一会儿......如果是这样,你可以发布工作的例子吗? – 2010-06-21 12:52:09