[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 668
  • Last Modified:

Where Did I Go Wrong in My Echo Client/Server? getaddrinfo() - C++

Not the best code out there but i would like to know why my program is forced to exit after i insert IP and Port.

This is where it goes wrong, "getFullAddressInformation(ip, port, hints, serverInfo);" but i do not know why? Can you help please...

Program stops in here:

      std::cout<<"Please enter port's number: ";
      getline(std::cin, port);

      std::cout<<"SOMETHING GOES WRONG IN HERE!"<<std::endl;
      system("pause");

      getFullAddressInformation(ip, port, hints, serverInfo);

Regarding the port and ip,  i get them as string and convert them to const *char in here
getaddrinfo(ipAddress.c_str(), portNumber.c_str(), &giveHints, &receiveServerInfo);

#include<iostream>
#include<string>
#include<sstream>
#include<ws2tcpip.h>
 
#define MAX_DATA 1024			//maximum bytes could be sent or received 
 
 
void initiateWinsockFacility()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    int error;
 
    wVersionRequested = MAKEWORD(2, 2);
 
    error = WSAStartup(wVersionRequested, &wsaData);
 
    if (error != 0) 
	{
		std::cerr<<"WSAStartup failed with error: "<<error<<std::endl;
 
		system("pause");
                exit(-1);
    }
}
 
//output, to receiveServerInfo, full information about the connection to be made
void getFullAddressInformation(std::string ipAddress, std::string portNumber, const struct addrinfo giveHints, struct addrinfo *receiveServerInfo)
{
	int status = getaddrinfo(ipAddress.c_str(), portNumber.c_str(), &giveHints, &receiveServerInfo);
	
	if(status != 0)
	{
		std::cerr<<"getaddrinfo() error: "<< gai_strerror(status) <<std::endl;
		WSACleanup();
 
		system("pause");
		exit(-1);
	}
}
 
int main()
{
	struct addrinfo hints;      	    //input connection type and ip type 
	struct addrinfo *serverInfo = NULL;	//holds full address information of a server
	SOCKET socketFileDescriptor;
	char userInput[MAX_DATA];      
	char serverResponse[MAX_DATA];
	std::string ip;
	std::string port;
 
	initiateWinsockFacility();
 
	system("cls");
 
	memset(&hints, 0, sizeof(hints));
 
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
 
	std::cout<<"Please enter server's IP: ";
	getline(std::cin, ip);
 
	std::cout<<"Please enter port's number: ";
	getline(std::cin, port);
 
	std::cout<<"SOMETHING GOES WRONG IN HERE!"<<std::endl;
	system("pause");
 
	getFullAddressInformation(ip, port, hints, serverInfo);
 
	try
	{
		socketFileDescriptor = socket(serverInfo->ai_family, serverInfo->ai_socktype, serverInfo->ai_protocol);
		if(socketFileDescriptor == INVALID_SOCKET )
		{
			std::cerr<<"socket() error: " << WSAGetLastError() <<std::endl;
			throw 1;
		}
 
		std::cout<<"connecting to the server ..."<<std::endl;
 
		int connectStatus = connect(socketFileDescriptor, serverInfo->ai_addr, serverInfo->ai_addrlen);
		if(connectStatus == SOCKET_ERROR)
		{
			std::cerr<<"connect() error: " << WSAGetLastError() <<std::endl;
			throw 2;
		}
 
		//send and receive messages
		while(true)
		{
			std::cout<<"\nyou: ";
			std::cin.getline(userInput, MAX_DATA);
			if(std::cin.fail())
			{
				std::cerr<<"Overflow occured. Restart Application"<<std::endl;
				throw 2;
			}
 
			int bytes_sent = send(socketFileDescriptor, userInput, strlen(userInput), 0);
 
			//chack whther bytes are sent fully or not
			while(bytes_sent != strlen(userInput))
			{
				//if bytes not sent fully, then see if its equal to socket error or not
				//if it is, then throw an error. If it isn't then ask user to resend data
				if(bytes_sent == SOCKET_ERROR)
				{
					std::cerr<<"send() error: " << WSAGetLastError() <<std::endl;
					throw 2;
				}
 
				//re-send
				std::cout<<"\nyou: ";
				std::cin.getline(userInput, MAX_DATA);
				if(std::cin.fail())
				{
					std::cerr<<"Overflow occured. Restart Application"<<std::endl;
					throw 2;
				}
 
				int bytes_sent = send(socketFileDescriptor, userInput, strlen(userInput), 0);
 
			}
 
			int bytes_received = recv(socketFileDescriptor, serverResponse, MAX_DATA, 0);
			
			//make sure the returned value is socket error and not zero
			if((bytes_received == SOCKET_ERROR) && (bytes_received != 0))
			{
				std::cerr<<"recv() error: " << WSAGetLastError() <<std::endl;
				throw 2;
 
			}else{ //returned value is zero which means the server shut down
				std::cout<<"server shut down"<< std::endl;
				break;
			}
 
			std::string echoedMsg(serverResponse, bytes_received);
			std::cout<<"server: "<< echoedMsg << std::endl;
		}
	}
	catch(int v)
	{
		if(v == 1)
		{
			freeaddrinfo(serverInfo);
			WSACleanup();
 
			system("pause");
			exit(-1);
		}
 
		if(v == 2)
		{
			closesocket(socketFileDescriptor);
			freeaddrinfo(serverInfo);
			WSACleanup();
 
			system("pause");
			exit(-1);
		}
	}
 
	closesocket(socketFileDescriptor);
	freeaddrinfo(serverInfo);
        WSACleanup();
 
	system("pause");
	return 0;
}

Open in new window

0
F-J-K
Asked:
F-J-K
1 Solution
 
jkrCommented:
You are not checking whether 'serverInfo' is non-NULL after 'getFullAddressInformation()' returns, which results in an access violation when reading from it in the 'socket()' call. Just add

if (serverInfo == NULL) {

  std::cerr << "No valid information";

  exit(-2);
}
0
 
DanRollinsCommented:
Use the debugger to single-step through your code.  
Most problems (at least at this level of programming) become instantly obvious when you single-step from line to line and use the debugger to examine variables, etc.
0
 
Infinity08Commented:
>> You are not checking whether 'serverInfo' is non-NULL after 'getFullAddressInformation()' returns,

It WILL be NULL at all times, so checking it will only avoid the crash - it will not make the code work.

You need to pass serverInfo pointer by pointer-to-pointer, or by reference. Right now, you're passing the pointer by value, so the changes done to it inside getFullAddressInformation will not be visible in main. In main, serverInfo will still be NULL after the getFullAddressInformation call.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
F-J-KAuthor Commented:
>>You need to pass serverInfo pointer by pointer-to-pointer, or by reference. Right now, you're passing the pointer by value, so the changes done to it inside getFullAddressInformation will not be visible in main. In main, serverInfo will still be NULL after the getFullAddressInformation call.

Ok. I did the following (check code snippet below).

I get this error:
error C2664: 'getFullAddressInformation' : cannot convert parameter 4 from 'addrinfo **' to 'addrinfo *'

for this line:
getFullAddressInformation(ip, port, hints, &serverInfo);

I tried to pass serverInfo by reference, so receiveServerInfo points to where serverInfo is pointing.


void getFullAddressInformation(std::string ipAddress, std::string portNumber, const struct addrinfo giveHints, struct addrinfo *receiveServerInfo)
{
	int status = getaddrinfo(ipAddress.c_str(), portNumber.c_str(), &giveHints, &receiveServerInfo);
	
	if(status != 0)
	{
		std::cerr<<"getaddrinfo() error: "<< gai_strerror(status) <<std::endl;
		WSACleanup();
 
		system("pause");
		exit(-1);
	}
}
 
//**************************
 
struct addrinfo *serverInfo = NULL;
.
.
.
getFullAddressInformation(ip, port, hints, &serverInfo);

Open in new window

0
 
Infinity08Commented:
You should also modify the function signature to take the correct argument type, and the function implementation to use the argument correctly.
0
 
F-J-KAuthor Commented:
Thanks...It helped
0

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now