Solved

I Wrote A Simple TCP Server. I Get Weird Output - Why? C/C++ Socket Programming

Posted on 2008-10-31
5
1,131 Views
Last Modified: 2013-11-13
Simple server that listens on port 10030. Once a client connects to it, the server sends back a message to the client says "Hello To Socket Programming World!" then closes the socket. Use telnet as the client. It works fine, but the server output is not as expected.

Why does the client's ip address appear as follows:

Sent 35 bytes to client : ::aff:c0fd:7fbf
Sent 35 bytes to client : ::ffff:127.0.0.1
Sent 35 bytes to client : ::ffff:127.0.0.1
Sent 35 bytes to client : ::ffff:127.0.0.1

1. The fist IP address appears as ::aff:c0fd:7fbf
the second appears as ::ffff:127.0.0.1
I think i only should get 127.0.0.1, i'm not using any IPv6. Do you know why?

2. Why IP at first time appears differently than the rest?

Look at this function - void *get_in_addr(struct sockaddr *clientAddress) as its the one that fetches client's IP address...

Please help!
#include<iostream>

#include<string>

#include<sstream>

#include<sys/types.h>

#include<sys/socket.h>

#include<netdb.h>

#include<arpa/inet.h>

#include<errno.h> 

using namespace std;

 

#define PORT "10030" // the port users will be connecting to - the port we (server) will be listening on

#define BACKLOG 10   // how many pending connections queue will hold

 

//describe the program

void progDesc()

{

	cout<<"This server listens for a connection from client, andreplies\n";

	cout<<"back to the client with a message, then closes the socket"<<endl;

}

 

//get sockaddr, IPv4 or IPv6:

void *get_in_addr(struct sockaddr *clientAddress)

{

	void *addr;

	

	//check the version of client's IP

	if (clientAddress->sa_family == AF_INET) {

		struct sockaddr_in *ipv4 = (struct sockaddr_in *)clientAddress;

		addr = &(ipv4->sin_addr);

		return addr;

	}else{

		struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)clientAddress;

		addr = &(ipv6->sin6_addr);

		return addr;

   	}

}

 

 

int main()

{

	int serverSockD;           //the server's socket that listen incoming connections

	int clientSockD;           //the client's socket that works as a medium between client and server to send(), recv(), etc

	struct addrinfo hints;     //get inputs about the server information

 

	struct addrinfo *servInfo; 

 

	struct sockaddr clientInfo;			     //obtains clients information once accept succeed

	socklen_t clientInfo_size; 			     //holds the size of cleintInfo

	char msg[] = "Hello To Socket Programming World!\n"; //message that is sent back to client

 

	//set size of hints to zero

 

	memset(&hints, 0, sizeof hints);

 

 

 

	//fill some of the server info (your current host info)

 

	hints.ai_family = AF_UNSPEC;

 

	hints.ai_socktype = SOCK_STREAM;

        hints.ai_flags = AI_PASSIVE;     //your (the server's) local ip address will be specified 

                                         //automatically. The server can have more than one ip address.

 

	//get a more specific server's information, such as IP Addresses, and pass the output to servInfo

	int status = getaddrinfo(NULL, PORT, &hints, &servInfo);

	

	//make sure getaddrinfo succeeded

	if(status != 0)

 

	{

 

		fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));

 

		return 1;

 

	}

 

        //create a socket - this socket will be used to listen on PORT for incoming connections

	serverSockD = socket(servInfo->ai_family, servInfo->ai_socktype, servInfo->ai_protocol);

 

	if(serverSockD == -1 )

 

	{

 

		cout<<"Error: failed to create a socket.\n";

 

		return 2;

 

	}

	

 

	//now bind the server socket to the ip address & port specified

	if(bind(serverSockD, servInfo->ai_addr, servInfo->ai_addrlen) == -1) 

	{

		perror("server: bind");

	        return 3;

	}

 

	//listen to the incoming connection, take up to 10 connections

	if(listen(serverSockD, BACKLOG) == -1) 

	{

	    perror("listen");

	    return 4;

	}

 

	//get the size of sockaddr struct of clientAddr

	clientInfo_size = sizeof clientInfo;

 

	//holds number of bytes sent

	int bytes_sent;

 

	//holds an IP address of the client's

	char printableClientIP[INET6_ADDRSTRLEN];

 

	//holds the exact IP address for the client() you accepted his/her connection

	void *clientIP;

 

	//listen forever, and accept all connections that come in

	//The only way we get out of the loop is in case of a crash 

	//or a user-initiated shutdown of the server

	while(1)

	{

		//accept pending connection. Information of incoming connection will go to clientInfo

		clientSockD = accept(serverSockD, &clientInfo, &clientInfo_size);

 

		if(clientSockD == -1)

		{

			perror("accept");

	   		return 5;

		}

 

		//send msg to the client & number of bytes sent will be returned

		bytes_sent = send(clientSockD, msg, strlen(msg), 0);

 

		//get_in_addr gives you the current client IP Address

		clientIP = get_in_addr(&clientInfo);

 

		//convert clientIP from numeric binary form to standard text form

		inet_ntop(clientInfo.sa_family, clientIP, printableClientIP, sizeof printableClientIP);

 

		//print to screen the IP Address of the client & how many bytes are sent

		printf("Sent %d bytes to client : %s\n", bytes_sent, printableClientIP);

 

		//close the current connection & repeat the loop to take the next connection

		close(clientSockD);

	}

 

	//free linkedlist of struct addrinfo *servInfo

 

	freeaddrinfo(servInfo);

	

	return 0;

}

Open in new window

0
Comment
Question by:F-J-K
  • 2
  • 2
5 Comments
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22856031
>>>> I think i only should get 127.0.0.1, i'm not using any IPv6.
Indeed, you don't as the higher numbers default to ffff. But the utility producing the output you posted was able to handle both IPv4 abd IPv6 hence you got it converted to the more universal one.

>>>> Why IP at first time appears differently than the rest?
The first IP is the one your provider had returned for the router after getting a request. The second IP 127.0.0.1 is your local IP which is only valid at your own computer. It would be used by your network device for local use only. In case you would operate more than one computer using the connection, you would need a router providing a local C-Net at your LAN, normally 192.168.xxx.yyy with xxx often is 0 or 1 and yyy goes from 1 to 255, where all computers needing a connection would get  one of the (only locally usable) IP address of the C-Net.
0
 
LVL 1

Author Comment

by:F-J-K
ID: 22858253
>>Indeed, you don't as the higher numbers default to ffff. But the utility producing the output you posted was able to handle both IPv4 abd IPv6 hence you got it converted to the more universal one.

Remember, i'm returning "addr", it either returns a total IPv4 or a total IPv6 ....
clientAddress->sa_family == AF_INET
if my cleintAddress is IPv4, then we return addr with IPv4. There won't be a chance to go to "else". Thats what makes me confuse.

>>The first IP is the one your provider had returned for the router after getting a request.
I'm using a telnet to connect to the simple tcp server,  the telnet is running on same machine "127.0.1.1". No third parties involved, such as routers, etc. Can you explain what do you exactly mean by "your provider" & what the router got to do with this as i'm not connecting from outside the network.

Thanks for your answer...I hope to hear from you!
0
 
LVL 53

Assisted Solution

by:Infinity08
Infinity08 earned 200 total points
ID: 22861038
Your network interface supports IPv6 addresses, so that's what it uses. The IPv6 address ::ffff:127.0.0.1 is the exact same address as the IPv4 address 127.0.0.1


>> if my cleintAddress is IPv4

Your client has an address, which might be represented as either IPv4 or IPv6. In this case, your protocol stack chose to represent it as IPv6.
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 300 total points
ID: 22861264
>>>> the telnet is running on same machine
Yes, but the telnet could run on each other computer in the wide world. Hence it uses an internal IP address which is already IPv6 and whcih was mapped to the 127.0.0.1 you have configured as only (default) OP address. That a mapping occurs you can see at the second line.

>>>> you exactly mean by "your provider"
Sorry I assumed you were connected to the internet. But even for a stand-alone computer, you have a TCP/IP configuration which internally uses IP addresses that were different to 127.0.0.1.
0
 
LVL 1

Author Closing Comment

by:F-J-K
ID: 31512169
Thanks! Your answers were clear and perfect! .......... Can't thank you enough!
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
haveThree challenge 22 100
withoutTen challenge 14 88
Copy Files - Python 7 56
Acrinis True image 2 13
How to remove superseded packages in windows w60 or w61 installation media (.wim) or online system to prevent unnecessary space. w60 means Windows Vista or Windows Server 2008. w61 means Windows 7 or Windows Server 2008 R2. There are various …
This article will show, step by step, how to integrate R code into a R Sweave document
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now