TCP仅适用于公共IP

时间:2012-01-22 19:50:31

标签: c winapi tcp ip

我写了两个函数,它们应该启动TCP-Server / Client。如果我用IP“127.0.0.1”调用它们(仅用于测试),那么一切正常。但是,如果我使用计算机的公共IP调用它们,我会收到连接超时。有谁知道可能是什么问题?

这里的代码:

服务器:

bool fSTARTED = false;
struct timeval tv;

TCP_StartServer (const int iPort, SOCKET *iSOCKET)
{
WSADATA wsa;
SOCKET iSOCKETListen;
SOCKADDR_IN tAdr;

if(!fSTARTED)
{
    if(WSAStartup(MAKEWORD(2,2), &wsa))
    {
        *iSOCKET = -1;
        return;
    }
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    fSTARTED = true;
}

iSOCKETListen = socket(AF_INET, SOCK_STREAM, 0);

memset(&tAdr, 0, sizeof(SOCKADDR_IN));
tAdr.sin_family = AF_INET;
tAdr.sin_port = htons(iPort);
tAdr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(iSOCKETListen, (SOCKADDR*) & tAdr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
    *iSOCKET = 0 - WSAGetLastError();
    return;
}

if(listen(iSOCKETListen, SOMAXCONN) == SOCKET_ERROR)
{
    *iSOCKET =  0 - WSAGetLastError();
    return;
}

*iSOCKET = accept(iSOCKETListen, NULL, NULL);
if(*iSOCKET == INVALID_SOCKET)
{
    *iSOCKET = 0 - WSAGetLastError();
    return;
}

return;
}

客户端:

TCP_StartClient (char *sIP, const int iPort, SOCKET *iSOCKET)
{
WSADATA wsa;
SOCKADDR_IN tAdr;

if(!fSTARTED)
{
    if(WSAStartup(MAKEWORD(2,2), &wsa))
    {
        *iSOCKET = -2;
        return;
    }
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    fSTARTED = true;

}

*iSOCKET = socket(AF_INET, SOCK_STREAM, 0);
if(*iSOCKET == INVALID_SOCKET)
{
    *iSOCKET = 0 - WSAGetLastError();
    return;
}

memset(&tAdr, 0, sizeof(SOCKADDR_IN));
tAdr.sin_family = AF_INET;
tAdr.sin_port = htons(iPort);
tAdr.sin_addr.s_addr = inet_addr(sIP);

if(connect(*iSOCKET, (SOCKADDR*) &tAdr, sizeof(SOCKADDR)) == SOCKET_ERROR)
{
    *iSOCKET =  0 - WSAGetLastError();
    return;
}

return;
}

2 个答案:

答案 0 :(得分:3)

以下是典型家庭计算机网络的外观(简化图表和说明):

        \     Internet     /
         \/\/\/\/\/\/\/\/\/
                  |
                  | 212.60.44.90 (public IP address)
           +-------------+
           | DSL router  |
           +-------------+
                  | 10.0.0.1 (private network router)
                  |
                  | 10.0.0.2 (private network address)
           +-------------+
           |Your computer|
           +-------------+

在这种情况下,路由器正在从您的本地10.0.0.x地址到您的公共212.60.44.90地址NAT。您的计算机不知道它最终使用的公共IP地址,因为该信息仅在DSL路由器中。 NAT的一点是,本地10.0.0.x网络上可能还有其他计算机,并且它们共享相同的公共IP地址(因为只有一个)。

您的路由器可能还充当防火墙,防止来自Internet的随机传入连接到达您的本地计算机。通常,路由器将阻止所有这样的传入连接。

鉴于上述情况,您应该能够了解为什么无法从 自己的网络中连接到公共212.60.44.90地址。您的计算机将请求发送到路由器,路由器会从防火墙的角度忽略或阻止您的请求。

根据您的路由器,可能能够将其配置为将您的公共IP地址的传入请求转发到10.0.0.x网络上的特定计算机。您必须手动设置,并且有关如何执行此操作的说明超出了此答案的范围。

此外,您可能会注意到您应该能够在本地网络地址(图中的10.0.0.2)上连接到本地计算机。但是,这并不比连接到127.0.0.1更有趣。

答案 1 :(得分:0)

这可能不是您的代码的问题。尝试从外部IP访问时,某些计算机(如我的)无法看到自己。尝试为外部IP设置环回适配器,同时检查NAT规则。