3

I have a server running on one machine and have the port it uses forwarded to my router, and another machine running the client connecting to the server using my ISP assigned external IP address instead of the local address. This all works fine and it connects but When I check the address of the connected socket (client), The IP address that it shows is completely different? it shows me 148.49.68.0. I can't find this on ipconfig and don't understand where this is popping up from. Shouldn't the client show my external address? (seeing as both computers use the same External IP address).

[EDIT] added server source

#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;
}
silent
  • 2,836
  • 10
  • 47
  • 73

4 Answers4

9

Try this:

#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; 
} 
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

enter image description here

One c/c++ way of getting the external ip is to use a web based IP address API tool, download the webpage containing your IP address into a char array and extract the IP address from the HTML source. Here is some winsock code to demonstrate it. it uses http://api.ipify.org/ 's online web 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;
}
Software_Designer
  • 8,490
  • 3
  • 24
  • 28
  • That is not what he was asking for. What you're doing, you're retrieving someone's `public IP`. Further still, are you sure that the `ipify.org` service will be around for your approach to work? – ahmd0 Mar 23 '18 at 06:07
0

The WinSock getsockname() and getpeername() functions return the local and remote IPs of the connected socket, respectively. Assuming you are already using them, then please show your actual code, as you are likely not using them correctly.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Hello, I did not use getsockname or getpeername, I figured the sockaddr received to the server about the client would already hold this. I will edit the post above, please advise me how. – silent Nov 26 '10 at 08:15
  • 2
    Yes, accept() does return information about the connected client. However, there are quite a few bugs in your code. The most important bug related to your original question is that your Accept() function is retrieving the client info into a sockaddr_in variable that is local only to Accept(), but then your connection_info() function is displaying values from a different sockaddr_in that is local to main() instead and was never filled in with any data, so you are displaying random garbage. Your Accept() function needs to return the sockaddr_in data it retreived, not discard it. – Remy Lebeau Nov 27 '10 at 01:05
0

(The following is Windows specific.)

Granted that a AF_INET6 type socket can be configured to accept both IPv4 and IPv6 connections on to the same port:

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

I would implement retrieval of the client connection stats as such, right after the accept function:

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());
}

Note that the port number reported will be for the connection on the client side (and not the server-side where this code is running.)

And, by the way, if you want to retrieve the same info but on the server-side of the connection, use the exact same code but replace getpeername with getsockname.

ahmd0
  • 16,633
  • 33
  • 137
  • 233