连接到外部IP失败

时间:2014-12-23 15:15:38

标签: c++ sockets networking tcp winsock

我多年来一直坚持这个问题......

所以我使用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或类似的连接。所以现在我想知道,如何检测我是否连接到我托管的服务器?那将是一个很好的伎俩。新年快乐!

2 个答案:

答案 0 :(得分:1)

没有控制台很难帮助你...但你可以和你的朋友谈谈并试试这个:

  • 从您朋友的电脑上对您的服务器进行ping操作。
  • 如果您收到答案,请使用tracert或traceroute找出问题所在
  • 你朋友的路线模特是什么?可能它有一个系统事件日志,您可以在其中检查被拒绝的连接。

运气!

答案 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;
}