TCP только не работает с публичным IP - PullRequest
2 голосов
/ 22 января 2012

Я написал две функции, которые должны запускать TCP-сервер / клиент.Если я называю их с 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 ]

3 голосов
/ 24 января 2012

Вот как выглядит типичная домашняя компьютерная сеть (упрощенная схема и пояснение):

        \     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|
           +-------------+

В этом случае маршрутизатор выполняет NAT с локальных адресов 10.0.0.x на общедоступный адрес 212.60.44.90. Ваш компьютер не знает об общедоступном IP-адресе, который он в конечном итоге использует, потому что эта информация находится только в маршрутизаторе DSL. Смысл NAT заключается в том, что в вашей локальной сети 10.0.0.x могут быть и другие компьютеры, и они совместно используют один и тот же общедоступный IP-адрес (поскольку существует только один).

Ваш маршрутизатор, вероятно, также действует как брандмауэр, предотвращая случайное поступление входящих подключений из Интернета на локальные компьютеры. Обычно маршрутизатор блокирует все такие входящие соединения.

Учитывая вышесказанное, вы сможете понять, почему вы не можете подключиться к общедоступному адресу 212.60.44.90 из в вашей собственной сети. Ваш компьютер отправляет запрос маршрутизатору, который либо игнорирует, либо блокирует ваш запрос с точки зрения брандмауэра.

В зависимости от вашего роутера, вы можете настроить его так, чтобы он перенаправлял входящие запросы на ваш общедоступный IP-адрес на определенный компьютер в вашей сети 10.0.0.x. Вам придется настроить это вручную, и инструкции о том, как это сделать, выходят за рамки этого ответа.

Кроме того, вы можете заметить, что вы должны иметь возможность подключиться к локальному компьютеру по адресу локальной сети (10.0.0.2 на схеме). Однако это не намного интереснее, чем подключение к 127.0.0.1.

0 голосов
/ 22 января 2012

Это может даже не быть проблемой с вашим кодом. Некоторые компьютеры (например, мой) не видят себя при попытке доступа с внешнего IP. Попробуйте установить петлевой адаптер для внешнего IP-адреса, а также проверьте правила NAT.

...