2016-12-07 3 views
-1

Я использую NO-IP, чтобы указать мой общий адрес, также я пересылаю порт 8844, но все же мой сервер не работает. когда я пытаюсь «127.0.0.1» вместо того, чтобы провести это работает, я не смог найти, где ошибка ..C++ Windows can not bind socket

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nShow) 
{ 
    WORD sockVer; 
    WSADATA wsaData; 
    int retVal; 

    sockVer = MAKEWORD(2, 2); 

    WSAStartup(sockVer, &wsaData); 

    /// Creating socket 
    SOCKET servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 

    if (servSock == INVALID_SOCKET) 
    { 
     MessageBox(NULL, "Unable to create socket()", "SOCKET ERROR", MB_OK); 
     WSACleanup(); 
     return SOCKET_ERROR; 
    } 

    /// Filling in sockaddr_in struct 

    struct hostent* host = gethostbyname("myhostadress"); 

    SOCKADDR_IN sin; 
    sin.sin_family = AF_INET; 
    sin.sin_port = htons(8844); 
    sin.sin_addr.s_addr = inet_addr(host->h_addr); 




    retVal = bind(servSock, (LPSOCKADDR)&sin, sizeof(sin)); 
    if (retVal == SOCKET_ERROR) 
    { 
     MessageBox(NULL, "Unable to bind", "SOCKET ERROR", MB_OK); 

     WSACleanup(); 
     return WSAGetLastError(); 
    } 
+0

И номер ошибки был? NB номер ошибки * до * вы вызываете 'WSACleanup()'. Публикация вопроса без сообщения об ошибке или номера здесь является пустой тратой времени. – EJP

+0

захватите 'WSAGetLastError()' перед вызовом 'WSACleanup' и распечатайте его. Затем просмотрите здесь код ошибки (https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668 (v = vs.85) .aspx), чтобы узнать, что произошло. – user4581301

+0

Затем найдите код ошибки в ** MSDN **, чтобы узнать, что произошло. @ user4581301 – EJP

ответ

1

Вы используете gethostbyname() (без проверки ошибок), чтобы получить публичный IP (Есть и другие способы, чтобы получить этот IP без использования DNS-поиска). Если ваш сервер находится за NAT/маршрутизатором (как подразумевается вашим комментарием, что вы должны перенаправить порт на свой сервер), тогда вы привязываетесь к неправильному IP-адресу. Вы можете привязываться только к IP-адресу, принадлежащему сетевому адаптеру, который является локальным для серверной машины. В среде NAT это означает привязку к IP-адресу частной сети, который был назначен серверу, а не публичному IP-адресу NAT. NAT будет перенаправлять соединения из своего общедоступного IP-адреса WAN на собственный IP-адрес сервера, а затем сервер может принимать соединения на своем личном IP-адресе LAN. Это также позволяет серверу принимать соединения от клиентов, работающих на других компьютерах с той же локальной сетью.

Кроме того, inet_addr() ожидает IP-адрес в формате точечной строки, но gethostbyname() вместо этого возвращает IP-адреса в двоичном формате. Когда поле hostent::h_addrtype равно AF_INET (которому не гарантируется возврат gethostbyname()), поле hostent::h_addr_list содержит указатели на in_addr структуры, которые затем можно назначить как-есть для поля sin.sin_addr.

Было бы проще просто привязать к INADDR_ANY, чтобы сервер мог принимать соединения по любому локальному IP-адресу, а не привязываться к конкретному IP-адресу.

Попробуйте это:

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nShow) 
{ 
    WSADATA wsaData; 
    int retVal; 

    retVal = WSAStartup(MAKEWORD(2, 2), &wsaData); 
    if (retVal != 0) 
    { 
     MessageBox(NULL, "Unable to initialize WinSock", "SOCKET ERROR", MB_OK); 
     return SOCKET_ERROR; 
    } 

    /// Creating socket 
    SOCKET servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (servSock == INVALID_SOCKET) 
    { 
     WSACleanup(); 
     MessageBox(NULL, "Unable to create socket", "SOCKET ERROR", MB_OK); 
     return SOCKET_ERROR; 
    } 

    /// Filling in sockaddr_in struct 

    SOCKADDR_IN sin = {0}; 
    sin.sin_family = AF_INET; 
    sin.sin_port = htons(8844); 
    //sin.sin_addr.s_addr = inet_addr("192.16.0.1"); // whatever your LAN IP is 
    sin.sin_addr.s_addr = INADDR_ANY; 

    retVal = bind(servSock, (LPSOCKADDR)&sin, sizeof(sin)); 
    if (retVal == SOCKET_ERROR) 
    { 
     retVal = WSAGetLastError(); 
     MessageBox(NULL, "Unable to bind socket", "SOCKET ERROR", MB_OK); 
     closesocket(servSock); 
     WSACleanup(); 
     return SOCKET_ERROR; 
    } 

    retVal = listen(servSock, ...); 
    if (retVal == SOCKET_ERROR) 
    { 
     retVal = WSAGetLastError(); 
     MessageBox(NULL, "Unable to listen on socket", "SOCKET ERROR", MB_OK); 
     closesocket(servSock); 
     WSACleanup(); 
     return SOCKET_ERROR; 
    } 

    ... 

    closesocket(servSock); 
    WSACleanup(); 

    return 0; 
} 

В качестве альтернативы, вы можете использовать getaddrinfo() вместо и пусть он расскажет вам, какие IP (ы) для привязки к:

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nShow) 
{ 
    WSADATA wsaData; 
    int retVal; 

    retVal = WSAStartup(MAKEWORD(2, 2), &wsaData); 
    if (retVal != 0) 
    { 
     MessageBox(NULL, "Unable to initialize WinSock", "SOCKET ERROR", MB_OK); 
     return SOCKET_ERROR; 
    } 

    addrinfo hints = {0}; 
    hints.ai_flags = AI_PASSIVE; 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_protocol = IPPROTO_TCP; 

    addrinfo *addrs 
    retVal = getaddrinfo(NULL, "8844", &hints, &addrs); 
    if (retVal != 0) 
    { 
     MessageBox(NULL, "Unable to get addr info", "SOCKET ERROR", MB_OK); 
     WSACleanup(); 
     return SOCKET_ERROR; 
    } 

    std::vector<SOCKET> servSocks; 

    /// Creating sockets 
    for(addrinfo *addr = addrs; addr != NULL; addr = addr->ai_next) 
    { 
     SOCKET servSock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 
     if (servSock == INVALID_SOCKET) 
      continue; 

     retVal = bind(servSock, addr->ai_addr, addr->ai_addrlen); 
     if (retVal == SOCKET_ERROR) 
     { 
      closesocket(servSock); 
      continue; 
     } 

     retVal = listen(servSock, ...); 
     if (retVal == SOCKET_ERROR) 
     { 
      closesocket(servSock); 
      continue; 
     } 

     servSocks.push_back(servSock); 
    } 

    freeaddrinfo(addrs); 

    if (servSocks.empty()) 
    { 
     MessageBox(NULL, "Unable to prepare listening socket(s)", "SOCKET ERROR", MB_OK); 
     WSACleanup(); 
     return SOCKET_ERROR; 
    } 

    ... 

    std::for_each(servSocks.begin(), servSocks.end(), &::closesocket); 
    WSACleanup(); 

    return 0; 
} 

В любом случае, ваш сервис NO-IP просто сопоставляет статическое имя хоста с текущим общедоступным IP-адресом NAT, не более того. Когда клиент хочет подключиться к имени хоста, он сначала разрешает имя хоста текущему IP-адресу, а затем подключается к этому IP-адресу. Он подключается к вашему NAT-маршрутизатору, а не к вашему серверу напрямую. Маршрутизатор перенаправляет клиент на частный IP-адрес локальной сети, к которому привязан ваш сервер, где сервер может принять соединение. Поэтому убедитесь, что правила перенаправления портов вашего маршрутизатора настроены правильно. Если это не работает правильно, вы должны задать вопрос по адресу ServerFault.com, поскольку это проблема с сетью, а не проблема с кодировкой.

+0

Я получаю эту ошибку в servSo cks.push_back (servSocks): http://i.hizliresim.com/njLg2V.jpg – Elliot

+0

Опечатка с моей стороны. Я исправил это. '(servSocks)' должен быть '(servSock)' вместо. –

+0

Также как я могу добавить свой ip в качестве имени хоста к этому, извините, мой мозг работает так медленно, теперь я не спал 27+ часов. – Elliot