На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > Не получается обратится к http-серверу по ip.
      Windows, WinSock.
      Создается сокет, привязывается к локальному ip-адресу (127.0.0.1, порт 8000), вызывается listen, а потом accept, получаем клиентское соединение, получаем данные, которые прислал клиент.
      Набрав в адресной строке браузера 127.0.0.1:8000, или [ip-адрес в локальной сети]:8000, серверу будет послан запрос от веб-браузера, который отобразится в консольном окне приложения, код которого представлен ниже.
      Как сделать так, чтобы я мог обращаться к этому серверному приложению из браузера по внешнему ip-адресу и порту, чтобы точно также браузер посылал свой запрос этому серверному приложению?
      Я так понял bind привязывает сокет только к адресу в локальной сети. Как же быть?
      Свой текущий ip-адрес я могу посмотреть, например здесь https://2ip.ru/. Как по нему обратится к моему серверу (код ниже)?

      ExpandedWrap disabled
        #include <stdio.h>
        #include <stdlib.h>
        #include <locale.h>
         
        #include <WinSock2.h>
        #include <WS2tcpip.h>
        #pragma comment(lib, "Ws2_32.lib")
        #include <iostream>
        using namespace std;
         
        in_addr getMyIP(){
            char buffer[100];
            ::gethostname(buffer,100);
            hostent* ipAddr = ::gethostbyname(buffer);
            in_addr addr;
            memcpy(&addr,ipAddr->h_addr_list[0], sizeof(unsigned long));
            return addr;
        }
        char data[300] = {0};
        int main(){
            int error;
            setlocale(LC_ALL,"Russian_Russia.1251");
            WSADATA wsaData;
            WSAStartup(MAKEWORD(2, 2), &wsaData);
            struct addrinfo* addr = NULL;
            struct addrinfo 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;
            getaddrinfo("127.0.0.1", "8000", &hints, &addr);
        //getaddrinfo(inet_ntoa(::getMyIP()), "8000", &hints, &addr);//getMyIP() возвращает мой ip в локальной сети
        //getaddrinfo("###.###.###.###", "8000", &hints, &addr);//вместо "###.###.###.###" - мой текущий внешний ip, отображаемый например здесь https://2ip.ru/
            int serverSocket = socket(addr->ai_family, addr->ai_socktype,addr->ai_protocol);
            int r = bind(serverSocket, addr->ai_addr, (int)addr->ai_addrlen);
            if(r==SOCKET_ERROR){
                error = WSAGetLastError();
                printf("Не удалось привязать адрес к сокету.\nКод ошибки -- %i\n",error);
            }
            listen(serverSocket, 1);
            printf("Ожидание присоединения клиента...\n");
            int clientSocket = accept(serverSocket, NULL, NULL);
            if(clientSocket==INVALID_SOCKET){
                error = WSAGetLastError();
                printf("Не удалось получить клиентское соединение.\nКод ошибки -- %i\n",error);
            }else{
                printf("Клиентское соединение получено.\n");
            }
            int rin = ::recv(clientSocket,data,300,0);
            if(rin>0){//данные сервера приняты
                cout<<"запрос клиента:\n";
                cout<<data;
            }
            system("pause");
        }
        Надо bind делать на адрес 0.0.0.0:8000, тогда сервер будет слушать на всех интерфейсах.
          Цитата Pacific @
          Надо bind делать на адрес 0.0.0.0:8000, тогда сервер будет слушать на всех интерфейсах.

          Если сделать так, то теперь я могу одновременно обращаться к серверу так 192.168.100.37:8000 (мой адрес в локальной сети) или так 127.0.0.1:8000.
          Но мне нужно обращаться к моему серверному приложению по внешнему IP и порту, то есть по ip который отображается например здесь https://2ip.ru/.
          Сообщение отредактировано: riden -
            Цитата riden @
            Но мне нужно обращаться к моему серверному приложению по внешнему IP и порту, то есть по ip который отображается например здесь https://2ip.ru/.
            Если внешний IP не привязан ни к одному интерфейсу, то повесить приложение на него не удастся.
            В таком случае приложение вешается на IP интерфейса, через который компьютер выход в Интернет.
            Если компьютер подключен через роутер, то нужно на нем пробросить 8000 порт на IP интерфейса компьютера (на 192.168.100.37).
              Цитата simsergey @
              ... через роутер, то нужно на нем пробросить 8000 порт на IP интерфейса компьютера (на 192.168.100.37).

              Скажите пожалуйста как это сделать.
                Ды обычно очень просто.
                Эта тема заезженная. Вот например тут инструкции.

                Другое дело, если бы это делать самой программой, так было бы интереснее. Но мне не приходилось.
                Можно самой программой по технологии UPnP делать проброс порта на роутере.
                  Цитата simsergey @
                  Ды обычно очень просто.
                  Эта тема заезженная. Вот например тут инструкции.

                  Другое дело, если бы это делать самой программой, так было бы интереснее. Но мне не приходилось.
                  Можно самой программой по технологии UPnP делать проброс порта на роутере.

                  Открыл порт в настройках роутера. http://2ip.ru показывает, что порт 8000 открыт. При проверке порта, на этом сайте, серверное приложение (код ниже) пишет "Клиентское соединение установлено".
                  Но, если в адресной строке браузера набрать мой внешний ип и порт (###.###.###.###:8000), то по-прежнему ничего не происходит.
                  При этом если набрать 192.168.100.37:8000 то все будет работать как и ожидается: в окне серверного приложения отобразится запрос веб-браузера. Что не так?
                  ExpandedWrap disabled
                    #include <stdio.h>
                    #include <stdlib.h>
                    #include <locale.h>
                     
                    #include <WinSock2.h>
                    #include <WS2tcpip.h>
                    #pragma comment(lib, "Ws2_32.lib")
                    #include <iostream>
                    using namespace std;
                     
                    char data[300] = {0};
                    int main(){
                        int error;
                        setlocale(LC_ALL,"Russian_Russia.1251");
                        WSADATA wsaData;
                        WSAStartup(MAKEWORD(2, 2), &wsaData);
                        struct addrinfo* addr = NULL;
                        struct addrinfo 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;
                        getaddrinfo("192.168.100.37", "8000", &hints, &addr);
                        int serverSocket = socket(addr->ai_family, addr->ai_socktype,addr->ai_protocol);
                        int r = bind(serverSocket, addr->ai_addr, (int)addr->ai_addrlen);
                        if(r==SOCKET_ERROR){
                            error = WSAGetLastError();
                            printf("Не удалось привязать адрес к сокету.\nКод ошибки -- %i\n",error);
                        }
                        listen(serverSocket, 1);
                        printf("Ожидание присоединения клиента...\n");
                        int clientSocket = accept(serverSocket, NULL, NULL);
                        if(clientSocket==INVALID_SOCKET){
                            error = WSAGetLastError();
                            printf("Не удалось получить клиентское соединение.\nКод ошибки -- %i\n",error);
                        }else{
                            printf("Клиентское соединение получено.\n");
                        }
                        int rin = ::recv(clientSocket,data,300,0);
                        if(rin>0){//данные сервера приняты
                            cout<<"запрос клиента:\n";
                            cout<<data<<"\n";
                        }
                        system("pause");
                    }
                    Цитата riden @
                    Но, если в адресной строке браузера набрать мой внешний ип и порт (###.###.###.###:8000), то по-прежнему ничего не происходит.
                    А это уже или баг винды или роутера. Я с таким раньше сталкивался, когда не получается зайти на свой внешний IP.
                    Если Вы порт пробросили правильно, то остальные должны его видеть, ну а Вам остается коннектится на локальный.

                    Добавлено
                    Кстати, появление такого можно дополнительно проверить, повесив, скажем, http или ftp сервер, пробросив порт и на него.
                      Гляньте сюда
                      Думаю многое прояснится. :)
                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                      0 пользователей:


                      Рейтинг@Mail.ru
                      [ Script execution time: 0,0305 ]   [ 17 queries used ]   [ Generated: 28.03.24, 19:21 GMT ]