Winsocket не подключается к удаленному айпи. Почему?

Доброго времени суток, знатоки!

Написал две программы: сервер и клиент. Сервер открывает сокет и прослушивает тот порт, который задается после запуска, клиент подключается к айпи и к порту, которые тоже прописываются после запуска. Запускаю у себя сервер, открываю какой-нибудь порт, с клиента подключаюсь к 127.0.0.1 и к заданному порту; отправляю сообщения; профит. Если же мой друг запустит у себя сервер, а я попытаюсь подключиться с клиента к его айпи и порту, который он открыл - программа ждет секунд 15, потом выдает ошибку 10060 (превышено время ожидания подключения); если я запущу у себя сервер, открою порт, и попытаюсь подключиться к своему айпи и порту (НЕ 127.0.0.1), то происходит то же самое.

Прилагаю исходники обеих программ:
Сервер
#include <winsock2.h> 
#include <ws2tcpip.h>
#include <iostream>
#pragma comment (lib,"Ws2_32.lib")
 
using namespace std;
 
#define DEFAULT_BUFLEN 512
 
int main()
{
    WSADATA wsaData;
    int result;
    
    result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if(result != 0)
    {
        cout << "Error WSAStartup: " << result << endl;
        return -1;
    }
 
    struct addrinfo *aiResult = NULL, *ptr = NULL, hints;
    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;
    
    char* port;
    cout << "Set port: ";
    cin >> port;
 
    result = getaddrinfo(NULL, port, &hints, &aiResult);
    if (result != 0)
    {
        cout << "Error in getaddrinfo(): " << WSAGetLastError() << endl;
        WSACleanup();
        return -1;
    }
    
    SOCKET listenSocket = INVALID_SOCKET;
    listenSocket = socket(aiResult->ai_family, aiResult->ai_socktype, aiResult->ai_protocol);
    if(listenSocket == INVALID_SOCKET)
    {
        std::cout << "Error in socket(): " << WSAGetLastError();
        freeaddrinfo(aiResult);
        WSACleanup();
        return 1;
    }
    
    result = bind(listenSocket, aiResult->ai_addr, aiResult->ai_addrlen);
    if(result == SOCKET_ERROR)
    {
        cout << "Bind failed with error: " << WSAGetLastError() << endl;
        freeaddrinfo(aiResult);
        closesocket(listenSocket);
        WSACleanup();
        return -1;
    }
    freeaddrinfo(aiResult);
    
    if(listen(listenSocket, SOMAXCONN) == SOCKET_ERROR)
    {
        cout << "Listen failed with error: " << WSAGetLastError() << endl;
        closesocket(listenSocket);
        WSACleanup();
        return -1;
    }
    
    SOCKET ClientSocket = INVALID_SOCKET;
    ClientSocket = accept(listenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET) 
    {
        cout << "Accept failed with error: " << WSAGetLastError() << endl;
        closesocket(listenSocket);
        WSACleanup();
        return -1;
    }
    
    
    while(true)
    {
        char recvbuf[DEFAULT_BUFLEN] = "";
        int recvbuflen = DEFAULT_BUFLEN;
        result = recv(ClientSocket, recvbuf, recvbuflen, 0);
        if (result > 0)
        {
        //  cout << "Accepted " << result << " bytes" << endl;
            cout << "Received: " << recvbuf << endl;
        }
    }
 
    system("pause");
    return 0;
}


Клиент
#include <winsock2.h> 
#include <ws2tcpip.h>
#include <iostream>
#include <string>
#pragma comment (lib,"Ws2_32.lib")
 
using namespace std;
 
int main()
{
    WSADATA wsaData;
    int result;
    
    result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if(result != 0)
    {
        cout << "Error WSAStartup: " << result << endl;
        return -1;
    }
    
    SOCKET clientSocket = INVALID_SOCKET;
    clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(clientSocket == INVALID_SOCKET)
    {
        cout << "Error in socket(): " << WSAGetLastError() << endl;
        WSACleanup();
        return -1;
    }
    
    string ip;
    int port;
    
    cout << "Connect to:" << endl;
    cout << "IP: ";
    cin >> ip;
    cout << "Port: ";
    cin >> port;
    
    sockaddr_in clientService;
    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr(ip.c_str());
    clientService.sin_port = htons(port);
 
    result = connect(clientSocket, reinterpret_cast<SOCKADDR*>(&clientService), sizeof(clientService));
    if(result != 0) 
    {
        cout << "Error in connect(): " << WSAGetLastError() << endl;
        WSACleanup();
        return -1;
    }
    
    while(true)
    {
        string data = "";
        cout << "Enter a string: ";
        cin >> data;
        
        result = send(clientSocket, data.c_str(), data.size(), 0);
        if(result < 0)
        {
            cout << "Error in send(): " << WSAGetLastError() << endl;
            WSACleanup();
            return -1;
        }
    }
    
    closesocket(clientSocket);
    WSACleanup();
    
    system("pause");
    return 0;
}


В чем может быть дело? Заранее спасибо!

P.s. Свои айпишники мы с другом узнавали при помощи сайта 4it.me.
  • Вопрос задан
  • 393 просмотра
Пригласить эксперта
Ответы на вопрос 3
chumayu
@chumayu
Если в башне по*бень. То что еб*нь, что не еб*нь.
хм...так вы оба можете быть за NAT.
Купите пива и кабель 1-2 метра UTP обжатый...
Соедините два компа, одному 192.168.0.1 другому 192.168.0.2 поставьте порт за 20-30к
Тестируйте/Бухайте.
Ответ написан
Комментировать
@ipc_ngs
Помимо проброса порта к удаленному ПК через NAT (если он за роутером), нужно еще убедиться, что данный порт не блокируется файрволом на том ПК (отключить файерволл/брендмауер/антивирус или добавить порт в список разрешенных).. Но своем ПК тоже нужно порт в файерволле разрешить.
Ответ написан
Комментировать
15432
@15432
Системный программист ^_^
Как подключен к интернету ваш друг? Ваша схема сработает только, если ПК друга имеет тот самый IP, к которому вы пытаетесь подключиться.
Если ПК подключен через роутер, и IP принадлежит ему, нужно настроить проброс портов. Если же у роутера тоже не такой IP, а, например, 10.х.х.х, имеет место NAT и уже придется проброс портов организовывать на стороне интернет-провайдера. (или заниматься hole-punching'ом, когда при помощи внешнего сервера с реальным IP соединяются два ПК за NATом)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы