我多年来一直坚持这个问题......
所以我使用BSD套接字/ Winsock 2 TCP用多人游戏编写了一个游戏。我的服务器已启动并正常工作,我可以在本地连接(通过填写我自己的外部IP间接)。一切似乎都很好。我用canyouseeme.org测试我的ip和服务器端口是否正确端口转发,它完全正常工作。然后我将我的客户端发送给朋友,通过连接到服务器来测试它,它一直都失败了。我希望他有连接,但我在服务器端看不到任何东西(而canyouseenme.org甚至弹出作为无效的客户端)。我不明白,我是否必须为TCP中的外部连接做一些特别的事情?
这是我的连接功能:
int CConnectSocket(CSocket s, unsigned short port, char* ipaddress)
{
SOCKADDR_IN target;
target.sin_family = AF_INET;
target.sin_port = htons(port);
target.sin_addr.s_addr = htonl(inet_addr(ipaddress));
if (connect(s, (SOCKADDR*)&target, sizeof(target)) == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEISCONN)
return CTCP_DONE;
else if (WSAGetLastError() != WSAEWOULDBLOCK && WSAGetLastError() != WSAEALREADY)
{
strcpy(inerr, "CConnectSocket: Failed to connect the socket. Error ");
char f[6];
sprintf(f, "%d", WSAGetLastError());
strcat(inerr, f);
return CTCP_ERROR;
}
return CTCP_WAIT;
}
return CTCP_DONE;
}
我一直循环这个函数,直到返回CTCP_DONE(意思是我已连接)。我的朋友报告说他超时(所以它返回CTCP_WAIT的时间太长了)。再次,我确定客户端是错误的,因为我的服务器能够接受来自canyouseeme.org的外部连接。我填写的IP地址和端口是因为我可以在本地连接。如果我更改端口,本地连接将不再起作用(证明它是正确的参数)。更改IP确实会产生相同的结果。
我感谢任何帮助!希望我能解决这个问题并开始多人游戏。
修改
void CEngine::CSetSockAddr(CSockAddr* address, unsigned short port, char* ipaddress)
{
memset(address, 0, sizeof(CSockAddr));
address->sin_family = AF_INET;
address->sin_port = htons(port);
address->sin_addr.s_addr = htonl(inet_addr(ipaddress));
}
这是我的套接字地址功能。当我删除htonl函数时,它在我朋友的一边工作,但不再在我身边(我也是托管服务器)。我的朋友BTW使用XP,但是因为我打电话使用2.2 WinSock应该没问题。至少我希望WinSock的setup函数在它返回true时保证2.2实现。
编辑2
大家好,
我现在已经完成所有工作了。似乎如果我添加htonl,我可以作为主机与外部IP连接,而不是与环回127.0.0.0.1或类似的连接。所以现在我想知道,如何检测我是否连接到我托管的服务器?那将是一个很好的伎俩。新年快乐!
答案 0 :(得分:1)
没有控制台很难帮助你...但你可以和你的朋友谈谈并试试这个:
运气!
答案 1 :(得分:0)
调用htonl()
时,您需要删除inet_addr()
来电。 connect()
期望IP处于网络字节顺序,inet_addr()
以网络字节顺序返回IP,因此无需在任何平台上交换字节。
试试这个:
int CConnectSocket(CSocket s, unsigned short port, char* ipaddress)
{
SOCKADDR_IN target = {0};
target.sin_family = AF_INET;
target.sin_port = htons(port);
target.sin_addr.s_addr = inet_addr(ipaddress);
if (connect(s, (SOCKADDR*)&target, sizeof(target)) == SOCKET_ERROR)
{
int err = WSAGetLastError();
switch (err)
{
case WSAEISCONN:
return CTCP_DONE;
case WSAEWOULDBLOCK:
case WSAEALREADY:
return CTCP_WAIT;
default:
sprintf(inerr, "CConnectSocket: Failed to connect the socket. Error %d", err);
return CTCP_ERROR;
}
}
return CTCP_DONE;
}