Определение IP-адреса подключенного клиента на сервере - PullRequest
3 голосов
/ 26 ноября 2010

У меня есть сервер, работающий на одной машине, и порт, который он использует, перенаправлен на мой маршрутизатор, а другая машина, на которой работает клиент, подключается к серверу, используя мой ISP назначенный внешний IP-адрес вместо локального адреса , Это все работает нормально, и он подключается, но когда я проверяю адрес подключенного сокета (клиента), IP-адрес, который он показывает, совершенно другой? это показывает мне 148.49.68.0. Я не могу найти это на ipconfig и не понимаю, откуда это появляется. Разве клиент не должен показывать мой внешний адрес? (поскольку оба компьютера используют один и тот же внешний IP-адрес).

[EDIT] добавлен серверный источник

#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string.h>
using namespace std;

int PORT;
const int winsock_version = 2;
const int max_con = 10;
string SERVER_ADDRS;

void Bind(SOCKET &serv,struct sockaddr_in &serv_info,int size);
void Listen(SOCKET &serv,int max_con);
void connection_info(struct sockaddr_in &client);
bool communication(SOCKET &client); 
SOCKET Accept(SOCKET &serv);

int main(void){

    WSADATA wsadata;
    if ( WSAStartup(MAKEWORD(winsock_version,0),&wsadata) == 0 ){
        cout<<"-[Initialized.]" << endl;
        cout<<"-[Server Address (leave blank to scan for all IP's)]: ";
        getline(cin,SERVER_ADDRS);
        cout<<"-[Port]: ";
        cin>>PORT;

        struct sockaddr_in serv_info;
        serv_info.sin_family = AF_INET;
        serv_info.sin_port = htons(PORT);
        if( sizeof(SERVER_ADDRS) > 5 ){
            cout<<"-[Listening on: " << SERVER_ADDRS << "]" << endl;
            serv_info.sin_addr.s_addr = inet_addr(SERVER_ADDRS.c_str());
        }else{
            cout<<"-[Scanning for All IP's]" << endl;
            serv_info.sin_addr.s_addr = INADDR_ANY;
        }

        SOCKET serv;
        serv = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        if ( serv != INVALID_SOCKET ){
            //------------------------------------------------------------
            Bind(serv,serv_info,sizeof(serv_info));
            Listen(serv,max_con);


            struct sockaddr_in client_info;
            int size = sizeof(client_info);

            SOCKET client_sock = Accept(serv);
            connection_info(client_info);

            if (communication(client_sock) == true){
                closesocket(serv);
                closesocket(client_sock);
            }
            //------------------------------------------------------------
        }

    }else{
        cout<<"-[Initialization failed, running cleanup.]" << endl;
    }

    if (WSACleanup() == 0){
        cout<<"-[Cleanup Successful.]" << endl;
    }

    return 0;
}

void Bind(SOCKET &serv,struct sockaddr_in &serv_info,int size){

    if ( bind(serv,(sockaddr*)&serv_info,size) != -1 ){
        //Binding complete, now clear the port and allow for reuse if needed using setsockopt
        char yes = '1';
        if ( setsockopt(serv,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) != SOCKET_ERROR){
                cout<<"-[Binding Successful.]" << endl;
        }
    }
}

void Listen(SOCKET &serv,int max_con){
    if ( listen(serv,max_con) != -1 ){
        cout<<"-[Listening for connections.] " << endl;
    }
}

SOCKET Accept(SOCKET &serv){

    struct sockaddr_in client_info;
    int size = sizeof(client_info);
    SOCKET recv;

    recv = accept(serv,(sockaddr*)&client_info,&size);
    if (recv != INVALID_SOCKET ) {
        return recv;
    }else{
        cout<<"-[Invalid Socket.]" << endl;
    }
}

void connection_info(struct sockaddr_in &client){
    char *connected_ip= inet_ntoa(client.sin_addr); 
    int port = ntohs(client.sin_port);

    cout<<"-[IP:" << connected_ip <<", Connected on PORT:"<< port  << "]"<< endl;
}

bool communication(SOCKET &client){
    cout<<"[---------------{CHAT}---------------]" << endl;
    int bytes_in;
    int bytes_out;
    char recvd_text[80];
    string send_text;

    while(true){
        cout<<"-[SERVER]: ";
        getline(cin,send_text);
        if (sizeof(send_text) > 0 ){
            bytes_out = send(client,send_text.c_str(),send_text.length()+1,0);
            cout<< endl;
            if (bytes_out == SOCKET_ERROR){
                cout<<"-[SERVER error in sending.]" << endl;
                break;
            }
        }

        bytes_in = recv(client,recvd_text,sizeof(recvd_text),0);
        if (bytes_in > 0 ){
            cout<<"-[CLIENT]: " << recvd_text << endl;  //output on screen
        }
        if (bytes_in == 0){
            cout<<"-[CLIENT has disconnected.]" << endl;
            break;
        }
        if (bytes_in == SOCKET_ERROR){
            cout<<"-[CLIENT closed unexpectedly.]" << endl; 
            break;
        }

    }
    return true;
}

Ответы [ 4 ]

8 голосов
/ 27 ноября 2010

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

#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string>

int PORT;
const int winsock_version = 2;
const int max_con = 10;
std::string SERVER_ADDRS;

void Bind(SOCKET &serv, const struct sockaddr_in &serv_info);
void Listen(SOCKET &serv, int max_con);
void connection_info(struct sockaddr_in &client);
bool communication(SOCKET client);
SOCKET Accept(SOCKET serv, sockaddr_in &client_info); 

int main(void)
{
    WSADATA wsadata; 
    if ( WSAStartup(MAKEWORD(winsock_version,0),&wsadata) == 0 )
    { 
        std::cout << "-[Initialized.]" << std::endl; 
        std::cout << "-[Server Address (leave blank to scan for all IP's)]: "; 
        std::getline(std::cin, SERVER_ADDRS); 
            std::cout << "-[Port]: "; 
        std::cin >> PORT; 

        struct sockaddr_in serv_info = {0}; 
        serv_info.sin_family = AF_INET; 
        serv_info.sin_port = htons(PORT); 
        if( SERVER_ADDRS.length() > 0 )
        { 
            std::cout << "-[Listening on: " << SERVER_ADDRS << "]" << std::endl; 
            serv_info.sin_addr.s_addr = inet_addr(SERVER_ADDRS.c_str()); 
        }
        else
        { 
            std::cout << "-[Scanning for All IP's]" << std::endl; 
            serv_info.sin_addr.s_addr = INADDR_ANY; 
        } 

        SOCKET serv = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
        if ( serv != INVALID_SOCKET )
        { 
            //------------------------------------------------------------ 
            Bind(serv, serv_info); 
            Listen(serv, max_con); 

            struct sockaddr_in client_info = {0}; 

            SOCKET client_sock = Accept(serv, client_info);
            if ( client_sock != INVALID_SOCKET )
            {
                connection_info(client_info); 
                communication(client_sock);

                closesocket(client_sock); 
            }
            //------------------------------------------------------------ 

            closesocket(serv); 
        } 


        if (WSACleanup() == 0)
        { 
            std::cout << "-[Cleanup Successful.]" << std::endl; 
        }
    }
    else
    { 
        std::cout << "-[Initialization failed.]" << std::endl; 
    } 

    return 0; 
} 

void Bind(SOCKET serv, const struct sockaddr_in &serv_info)
{ 
    //clear the port and allow for reuse before binding it
    int yes = 1; 
    if ( setsockopt(serv, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)) != SOCKET_ERROR)
    {
        std::cout << "-[Reuse Address Successful.]" << std::endl; 
    }

    if ( bind(serv, (sockaddr*)&serv_info, sizeof(serv_info)) != -1 )
    { 
        std::cout << "-[Binding Successful.]" << std::endl; 
    } 
} 

void Listen(SOCKET serv, int max_con)
{ 
    if ( listen(serv, max_con) != -1 )
    { 
        std::cout << "-[Listening for connections.] " << std::endl; 
    } 
} 

SOCKET Accept(SOCKET &serv, sockaddr_in &client_info)
{ 
    int size = sizeof(client_info); 
    SOCKET recv = accept(serv, (sockaddr*)&client_info, &size); 
    if ( recv == INVALID_SOCKET )
    { 
            std::cout << "-[Invalid Socket.]" << std::endl; 
    } 
    return recv; 
} 

void connection_info(struct sockaddr_in &client)
{ 
    char *connected_ip = inet_ntoa(client.sin_addr);
    int port = ntohs(client.sin_port); 

    st::cout << "-[IP:" << connected_ip << ", Connected on PORT:" << port << "]" << std::endl; 
} 

bool communication(SOCKET client)
{ 
    std::cout << "[---------------{CHAT}---------------]" << std::endl; 
    int bytes_in; 
    int bytes_out; 
    char recvd_text[81]; 
    std::string send_text; 

    while(true)
    { 
        std::cout << "-[SERVER]: "; 
        std::getline(std::cin,send_text); 
        if (send_text.length() > 0 )
        { 
            bytes_out = send(client, send_text.c_str(), send_text.length()+1, 0); 
            std::cout << std::endl; 
            if (bytes_out == SOCKET_ERROR)
            { 
                std::cout << "-[SERVER error in sending.]" << std::endl; 
                break; 
            } 
        } 

        bytes_in = recv(client, recvd_text, sizeof(recvd_text)-1, 0); 
        if (bytes_in == SOCKET_ERROR)
        { 
            std::cout << "-[CLIENT closed unexpectedly.]" << std::endl; 
            break; 
        } 
        else if (bytes_in == 0)
        { 
            std::cout << "-[CLIENT has disconnected.]" << std::endl; 
            break; 
        } 
        else
        {
            recvd_text[bytes_in] = 0;
            std::cout << "-[CLIENT]: " << recvd_text << std::endl;  //output on screen 
        }
    } 
    return true; 
} 
0 голосов
/ 23 марта 2018

(Ниже указана спецификация Windows.)

Предполагается, что сокет типа AF_INET6 можно настроить для приема подключений IPv4 и IPv6 к одному и тому же порту:

int ipv6only = 0;
setsockopt(hSock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only));

Я бы реализовал получение статистики клиентских подключений как таковой сразу после функции accept:

char Sadr[max(sizeof(sockaddr_in), sizeof(sockaddr_in6))] = {0};
int ncbSzSadr = sizeof(Sadr);
if(getpeername(hSockAccept, (sockaddr*)Sadr, &ncbSzSadr) == 0)
{
    if(ncbSzSadr == sizeof(sockaddr_in))
    {
        //IPv4
        sockaddr_in* psadr_v4 = (sockaddr_in*)Sadr;

        print("Connected to client from %s, port %u...\n", 
            inet_ntoa(psadr_v4->sin_addr),
            (int)htons(psadr_v4->sin_port));
    }
    else if(ncbSzSadr == sizeof(sockaddr_in6))
    {
        //IPv6
        sockaddr_in6* psadr_v6 = (sockaddr_in6*)Sadr;

        WCHAR buff[256];
        PCTSTR p_strIpv6 = InetNtop(AF_INET6, psadr_v6->sin6_addr, buff, _countof(buff));

        _tprintf(L"Connected to client from %s, port %u...\n", 
            p_strIpv6,
            (int)htons(psadr_v6->sin6_port));
    }
    else
    {
        _tprintf(L"ERROR: getpeername bad size=%d\n", ncbSzSadr);
    }
}
else
{
    _tprintf(L"ERROR: (%d) getpeername\n", WSAGetLastError());
}

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

И, кстати, если вы хотите получить ту же информацию, но на стороне соединения, используйте точно такой же код, но замените getpeername на getsockname.

0 голосов
/ 28 октября 2015

enter image description here

Один из способов получения внешнего ip на языке c / c ++ - использовать API-интерфейс для веб-адреса, загрузить веб-страницу, содержащую ваш IP-адрес, в массив char и извлечь IP-адрес из источника HTML. Вот некоторый код winsock, чтобы продемонстрировать это. он использует http://api.ipify.org/ онлайн веб-API.

//
// Winsock get external ip address from website api at   api.ipify.org
// api.ipify.org
//

#include <string.h>
#include <stdio.h>

#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <vector>

#include <algorithm>
#include <cctype>
#include <locale>
#include <fstream>
#include <ctime>
#include <cstdlib>

using namespace std;
#pragma comment(lib,"ws2_32.lib")


string website_HTML;
locale local;
char ipaddress[16];
int ic=0;
void get_Website(char *url );
char mystring[] = " ";
char seps[]   = " ,\t\n";
char *token;
char lineBuffer[200][80] ={' '};
char buffer[10000];
char ip_address[16];
int i = 0, bufLen=0, j=0,lineCount=0;
int lineIndex=0, posIndex=0;


int main( void ){

    SYSTEMTIME st;
    GetLocalTime(&st);
    char *today = new char[32];
    memset(today,' ', sizeof(today) );
    sprintf(today,"%d-%d-%d", st.wYear , st.wMonth , st.wDay);
    memset(buffer,'\0',sizeof(buffer));

    get_Website("api.ipify.org" );
    for (size_t i=0; i<website_HTML.length(); ++i) website_HTML[i]= tolower(website_HTML[i],local);

    token = strtok( buffer , seps );  
    while( token != NULL ){

      strcpy(lineBuffer[lineIndex],token);
      int dot=0;
      for (int ii=0; ii< strlen( lineBuffer[lineIndex] ); ii++ ){

          if (lineBuffer[lineIndex][ii] == '.') dot++;
          if (dot>=3){
              dot=0;
              strcpy(ip_address,lineBuffer[lineIndex]);
          }
      }

      token = strtok( NULL, seps );       
      lineIndex++;
   }
     cout<<"Your IP Address is  "<< ip_address<<" \n\n";

 return 0;
}


void get_Website(char *url ){
    WSADATA wsaData;
    SOCKET Socket;
    SOCKADDR_IN SockAddr;
    int lineCount=0;
    int rowCount=0;
    struct hostent *host;
    char *get_http= new char[256];

    memset(get_http,' ', sizeof(get_http) );
    strcpy(get_http,"GET / HTTP/1.1\r\nHost: ");
    strcat(get_http,url);
    strcat(get_http,"\r\nConnection: close\r\n\r\n");

    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0){
        cout << "WSAStartup failed.\n";
        system("pause");
        //return 1;
    }

    Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    host = gethostbyname(url);

    SockAddr.sin_port=htons(80);
    SockAddr.sin_family=AF_INET;
    SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);

    if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0){
        cout << "Could not connect";
        system("pause");
        //return 1;
    }
    send(Socket,get_http, strlen(get_http),0 );

    int nDataLength;
    while ((nDataLength = recv(Socket,buffer,10000,0)) > 0){        
        int i = 0;
        while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r'){

            website_HTML+=buffer[i];
            i += 1;
        }               
    }

    closesocket(Socket);
    WSACleanup();
    delete[] get_http;
}
0 голосов
/ 26 ноября 2010

Функции WinSock getsockname() и getpeername() возвращают локальный и удаленный IP-адреса подключенного сокета соответственно.Предполагая, что вы уже используете их, пожалуйста, покажите свой реальный код, поскольку вы, вероятно, используете их неправильно.

...