Client in C++, use gethostbyname or getaddrinfo - c++

I found the following code to open a connection in C:
int OpenConnection(const char *hostname, int port)
{
int sd;
struct hostent *host;
struct sockaddr_in addr = {0};
if ((host = gethostbyname(hostname)) == NULL)
{
perror(hostname);
abort();
}
sd = socket(PF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = *(long *)(host->h_addr_list[0]);
if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
{
close(sd);
perror(hostname);
abort();
}
return sd;
}
As I was rewriting this code in C++, I found out that I should be using getaddrinfo instead of gethostbyname, according to a comment in this post: C - What does *(long *)(host->h_addr); do?.
I was looking at Beej's guide to socket programming, and found the following example:
int status;
struct addrinfo hints;
struct addrinfo *servinfo; // will point to the results
memset(&hints, 0, sizeof hints); // make sure the struct is empty
hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
if ((status = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
// servinfo now points to a linked list of 1 or more struct addrinfos
// ... do everything until you don't need servinfo anymore ....
freeaddrinfo(servinfo); // free the linked-list
However, this example applies to creating a server, which makes me wonder
A] is getaddrinfosupposed to be used for clients
and
B] How would I modify the hints struct and the function parameters in order to make this code suitable for creating a client?
Currently, I have the following code but I
struct addrinfo hints = {0};
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo *client_info;
const int status = getaddrinfo(hostname, port, &hints, &client_info); //don't know if its correct
Update:
For anyone who may find it useful, here is my final code after reading the accepted answer:
int OpenConnection(const char *hostname, const char *port)
{
struct hostent *host;
if ((host = gethostbyname(hostname)) == nullptr)
{
//More descriptive error message?
perror(hostname);
exit(EXIT_FAILURE);
}
struct addrinfo hints = {0}, *addrs;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
const int status = getaddrinfo(hostname, port, &hints, &addrs);
if (status != 0)
{
fprintf(stderr, "%s: %s\n", hostname, gai_strerror(status));
exit(EXIT_FAILURE);
}
int sfd, err;
for (struct addrinfo *addr = addrs; addr != nullptr; addr = addr->ai_next)
{
sfd = socket(addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
if (sfd == ERROR_STATUS)
{
err = errno;
continue;
}
if (connect(sfd, addr->ai_addr, addr->ai_addrlen) == 0)
{
break;
}
err = errno;
sfd = ERROR_STATUS;
close(sfd);
}
freeaddrinfo(addrs);
if (sfd == ERROR_STATUS)
{
fprintf(stderr, "%s: %s\n", hostname, strerror(err));
exit(EXIT_FAILURE);
}
return sfd;
}

The gethostbyname() and gethostbyaddr() functions are deprecated on most platforms, and they don't implement support for IPv6. IPv4 has reached its limits, the world has been moving to IPv6 for awhile now. Use getaddrinfo() and getnameinfo() instead, respectively.
To answer your questions:
A. getaddrinfo() and getnameinfo() can be used for clients and servers alike, just as gethostbyname() and gethostbyaddr() can be. They are just host/address resolution functions, how the resolved values get used is up to the calling app to decide.
B. client code using getaddrinfo() would look something like this:
int OpenConnection(const char *hostname, int port)
{
int sd, err;
struct addrinfo hints = {}, *addrs;
char port_str[16] = {};
hints.ai_family = AF_INET; // Since your original code was using sockaddr_in and
// PF_INET, I'm using AF_INET here to match. Use
// AF_UNSPEC instead if you want to allow getaddrinfo()
// to find both IPv4 and IPv6 addresses for the hostname.
// Just make sure the rest of your code is equally family-
// agnostic when dealing with the IP addresses associated
// with this connection. For instance, make sure any uses
// of sockaddr_in are changed to sockaddr_storage,
// and pay attention to its ss_family field, etc...
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
sprintf(port_str, "%d", port);
err = getaddrinfo(hostname, port_str, &hints, &addrs);
if (err != 0)
{
fprintf(stderr, "%s: %s\n", hostname, gai_strerror(err));
abort();
}
for(struct addrinfo *addr = addrs; addr != NULL; addr = addr->ai_next)
{
sd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sd == -1)
{
err = errno;
break; // if using AF_UNSPEC above instead of AF_INET/6 specifically,
// replace this 'break' with 'continue' instead, as the 'ai_family'
// may be different on the next iteration...
}
if (connect(sd, addr->ai_addr, addr->ai_addrlen) == 0)
break;
err = errno;
close(sd);
sd = -1;
}
freeaddrinfo(addrs);
if (sd == -1)
{
fprintf(stderr, "%s: %s\n", hostname, strerror(err));
abort();
}
return sd;
}

I've always used gethostbyname() since "forever". It's always worked, it continues to work, and it's "simpler".
getaddrinfo() is the newer function:
http://man7.org/linux/man-pages/man3/getaddrinfo.3.html
The getaddrinfo() function combines the
functionality provided by the gethostbyname(3) and getservbyname(3)
functions into a single interface, but unlike the latter functions,
getaddrinfo() is reentrant and allows programs to eliminate
IPv4-versus-IPv6 dependencies.
I understand that getaddrinfo() ismore robust, more efficient, and more secure: You shouldn't be using gethostbyname() anyway
ADDENDUM:
In reply to your specific questions:
A] getaddrinfo() is preferred over gethostbyname() to lookup the IP address of a hostname; either "client" or "server".
B] Q: How would I modify the hints struct and the function parameters?
A: The "hints" look OK, but I would probably modify the port to NULL.
Here's a complete example:
https://www.kutukupret.com/2009/09/28/gethostbyname-vs-getaddrinfo/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
struct addrinfo hints, *res, *p;
int status;
char ipstr[INET6_ADDRSTRLEN];
if (argc != 2) {
fprintf(stderr, "Usage: %s hostname\n", argv[0]);
return 1;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 2;
}
for(p = res;p != NULL; p = p->ai_next) {
void *addr;
if (p->ai_family == AF_INET) {
return 1;
} else {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
/* convert the IP to a string and print it: */
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
printf("Hostname: %s\n", argv[1]);
printf("IP Address: %s\n", ipstr);
}
}
freeaddrinfo(res); // free the linked list
return 0;
}

Related

I don't know how to use Beej's programm from his Guide

1I'm reading Beej's programming network guide. I read his code and did an important change to check ipv6 but it's not working right. Can't get an ip Address. How to use this on a Linux system?
https://i.imgur.com/USVzBw1.png
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
struct addrinfo hints, *res, *p;
int status;
char ipstr[INET6_ADDRSTRLEN];
if (argc != 2) {
fprintf(stderr,"usage: showip hostname\n");
return 1;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 2;
}
printf("IP addresses for %s:\n\n", argv[1]);
for(p = res;p != NULL; p = p->ai_next) {
void *addr;
char *ipver;
// get the pointer to the address itself,
// different fields in IPv4 and IPv6:
if (p->ai_family == AF_INET) { // IPv4
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
} else if (p->ai_family==AF_INET6) { // IPv6
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}
// convert the IP to a string and print it:
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
printf(" %s: %s\n", ipver, ipstr);
}
freeaddrinfo(res); // free the linked list
return 0;
}```
This looks suspicious:
You check to make sure argc is 2 to validate you have at least one argument. Makes sense
if (argc != 2) {
But then later:
if ((status = getaddrinfo(argv[2], NULL, &hints, &res)) != 0) {
You reference argv[2], which is undefined when the only valid indicies in argv are 0 and 1.
Pretty sure you meant to use argv[1] as follows:
if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) {
Also, this is a bug:
// convert the IP to a string and print it:
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
printf(" %s: %s\n", ipver, ipstr);
Nothing wrong with those statements, but when p->ai_family is neither AF_INET nor AF_INET6, then those statements get executed anyway. addr and ipver are undefined. Hence, undefined behavior. And yes, on Linux, there's plenty of address types that are not IP based.
You are welcome to reference my ResolveHostname function on Github.

inet_ntop returns address that doesnt exist

#include <WinSock2.h>
#include <WS2tcpip.h>
#include "stdio.h"
int main(int argc, wchar_t *argv[]) {
//init Windows Sockets
//IResult
int IResult = NULL;
WSADATA wsaDataStruct;
IResult = WSAStartup(MAKEWORD(2, 2), &wsaDataStruct);
if (IResult != 0) // Error
{
//printf u are fucked;
printf("Error: Winsock2 Init, %d", IResult);
return 1;
}
//Result is output of getaddrinfo, hints is a helper struct
struct addrinfo*
result = NULL, //Linked list of addresses
* ptr = NULL,
hints = {};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
//Hostname
char hostname[64] = {};
gethostname(hostname, 64);
IResult = getaddrinfo(hostname, "4500", &hints, &result);
if (IResult != 0) { //Smth bad happened get Error
printf("Error: Winsock2 addrinfo, %d", IResult);
WSACleanup();
return 2;
}
//Loop addresses
addrinfo* addr = result;
while (addr!=nullptr)
{
char ip[16];
inet_ntop(addr->ai_family, addr->ai_addr, ip, 16);
printf("Address found: %s", ip);
addr = addr->ai_next;
}
return 0;
}
I am looping through the linked list of addrinfo structs and so far it returns one struct only which has an address of 2.0.17.148, while my machine has a local address of 192.168.2.1
I have only 1 network interface, and addrinfo returns a valid struct.
inet_ntop's argument should be a pointer to an in_addr (IPv4) or an in6_addr (IPv6).
You are passing it to a sockaddr, which will be a sockaddr_in for IPv4 or a sockaddr_in6 for IPv6. (You won't get any IPv6 addresses because you only asked for IPv4 addresses using AF_INET). The sockaddr contains the family code, the port, and the address.
To get the in_addr you need to access it within the sockaddr_in structure: First cast addr->ai_addr to sockaddr_in*, then access the sin_addr member, then get a pointer to it.
inet_ntop(addr->ai_family, &((sockaddr_in*)addr->ai_addr)->sin_addr, ip, 16);
Note: this only works for IPv4 (AF_INET family). To support IPv6 as well, you need to check whether the family is AF_INET or AF_INET6, and use sockaddr_in6 for AF_INET6, and allocate more space for ip because the addresses are longer.

How to establish custom message passing from AWS Ubuntu Virtual Machine to local PC

I am trying to set up a simple client-server system for message passing, using a local PC and a cloud virtual machine (Ubuntu 16) hosted by AWS. It's quite basic right now and will be extended using e.g. protobuf, but right now it's about creating a basic working example before I start integrating the communication scheme into my actual program.
The 'server' waits for a request from the 'client', and will then send the data to the client. The client is given the IP address of the server on startup.
If I run the server part on my AWS virtual machine and the client part on my local PC, everything works perfect, the data is transferred. However, it does not work the other way round, I cannot reach my local PC from the AWS virtual machine. I'm pretty sure AWS security groups are correct, since it works with the server running in the virtual machine. Also the IP of the local machine should be correct, since when running the server on the virtual machine, it output the IP of the client that requested the data.
I searched before in some forums, and I figured out it seems generally more complicated to reach the local PC from the AWS virtual machine. However, I didn't find a solution to my problem, and I assume it must be possible to send data from a cloud virtual machine to a local PC...
Thanks for any help!
***** Client side *****
-- call client with IP of server as arg --
#define PORT "3490" // the port client will be connecting to
int main(int argc, char *argv[])
{
int sockfd, numbytes;
unsigned char buf[MAXDATASIZE];
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
continue;
}
break;
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo);
if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
exit(1);
}
//deserialize and output data -- omitted
return 0;
}
***** Server side *****
int main(void)
{
srand (time(NULL));
mydata md0; //data structure that will be sent
//write members of md0 -- omitted
unsigned char buf[MAXDATASIZE],*ptr;
ptr = Serialize_mydata(buf,&md0);
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
continue;
}
break;
}
freeaddrinfo(servinfo); // all done with this structure
if (listen(sockfd, BACKLOG) == -1) {
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
exit(1);
}
printf("server: waiting for connections...\n");
while(1) { // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
continue;
}
inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
if (send(new_fd, buf, ptr - buf, 0) == -1)
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
return 0;
}

Create socket when have DNS name

Bellow is peace of code that I use to connect to socket in Windows. Sometimes I don't have IP dress, but have DNS name in inetAddr. Probably I must resolve address from host name, or it is possible create socket with DNS name? What is the best way to create socket when have DNS name?
commStatus communicate( const char * tx, char * rx, const int bufSize , const char * inetAddr, const int port )
{
...
SOCKET s;
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr(inetAddr);
server.sin_family = AF_INET;
server.sin_port = htons( port );
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
FILELOGL("Could not create socket : " << WSAGetLastError(),Level::Error );
} else
{
if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
{
FILELOGL("connect error", Level::Error);
r= commStatus::COMM_NO_TRANSMIT ;
} else
{
...
}
}
...
}
There is only one way: Resolve the host name.
Here's a part of my code that I've modified and haven't tested, but it should work:
WSADATA wsdata;
const char * inetAddr
addrinfo hints, *res;
WSAStartup (MAKEWORD (2, 2), &wsdata);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo("someaddress.com", NULL, &hints, &res) != 0)
return false;
inetAddr = inet_ntoa(((sockaddr_in *) res -> ai_addr) -> sin_addr);
You need to resolve the DNS name. Use getaddrinfo() for that. Just note that a DNS name can resolve to multiple IPs, both IPv4 and IPv6, so you have to call getaddrinfo() first in order to know how many IPs are reported, and what type of socket to create for each IP.
For example:
commStatus communicate( const char * tx, char * rx, const int bufSize , const char * inetAddr, const int port )
{
...
SOCKET s = INVALID_SOCKET;
struct addrinfo hint = {0};
hint.ai_flags = AI_NUMERICHOST;
hint.ai_family = AF_UNSPEC;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = IPPROTO_TCP;
struct addrinfo *addrs = NULL;
int ret = getaddrinfo(inetAddr, NULL, &hint, &addrs);
if (ret == EAI_NONAME)
{
hint.ai_flags = 0;
ret = getaddrinfo(inetAddr, NULL, &hint, &addrs);
}
if (ret != 0)
{
FILELOGL("Could not resolve inetAddr: " << ret, Level::Error);
}
else
{
for (struct addrinfo *addr = addrs; addr != NULL; addr = addr->ai_next)
{
s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (s == INVALID_SOCKET)
{
FILELOGL("Could not create socket : " << WSAGetLastError(), Level::Error);
break;
}
if (connect(s, addr->ai_addr, addr->ai_addrlen) == 0)
break;
closesocket(s);
s = INVALID_SOCKET;
if (addr->ai_next == NULL)
{
FILELOGL("connect error", Level::Error);
}
}
freeaddrinfo(addrs);
if (s != INVALID_SOCKET)
{
...
}
}
...
}

Can't get connect to work

I am working on some networking code. I have 2 solutions running on my same machine. The first is my server and the other is my client. I am using C++ and winsock for the networking solution.
Here is my server code (setup).
addrinfo hints;
addrinfo* pAddrInfo;
char pIPAddress[INET6_ADDRSTRLEN];
char pPortFinal[128];
unsigned long tempUL;
int error;
memset(&hints, 0, sizeof hints); // make sure the struct is empty
hints.ai_family = AF_UNSPEC;//AF_INET; // don't care IPv4 or IPv6
hints.ai_socktype = type;
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
error = getaddrinfo(NULL/*"localhost"*/, pPort, &hints, &pAddrInfo);
if(error != 0)
{
GetWinSockError(error);
return;
}
for(pAddrInfo = pAddrInfo; pAddrInfo != NULL; pAddrInfo = pAddrInfo->ai_next)
{
this->m_Socket = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, pAddrInfo->ai_protocol);
if(bind(this->m_Socket, pAddrInfo->ai_addr, pAddrInfo->ai_addrlen) != 0)
continue;
break;
}
if(!pAddrInfo)
{
GetWinSockError(WSAGetLastError());
freeaddrinfo(pAddrInfo);
this->ShutDown();
return;
}
//7 = magic number recommended by 'beej's guide' online
if(listen(this->m_Socket, 7) != 0)
{
GetWinSockError(WSAGetLastError());
freeaddrinfo(pAddrInfo);
this->ShutDown();
return;
}
getnameinfo(pAddrInfo->ai_addr, pAddrInfo->ai_addrlen, pIPAddress, sizeof pIPAddress, pPortFinal, sizeof pPortFinal, NI_NUMERICHOST | NI_NUMERICSERV);
this->m_pIPAddress = Helpers::String::NewCopy(pIPAddress);
this->m_pPort = Helpers::String::NewCopy(pPortFinal);
cout << "IP:" << this->m_pIPAddress << " Port:" << this->m_pPort << "\n";
this->SetState(NET_COMM_STATE__READY);
freeaddrinfo(pAddrInfo);
Here is my server code (tick).
NetServerClient* pNetComm;
sockaddr* pSockAddr;
sockaddr_storage their_addr;
socklen_t addr_size;
void* pTempBuffer;
char pIPAddress[INET6_ADDRSTRLEN];
char pPort[256];
unsigned short port;
int newClientSocket;
addr_size = sizeof their_addr;
newClientSocket = accept(this->m_Socket, (struct sockaddr*)(&their_addr), &addr_size);
if(newClientSocket == -1)
{
if(WSAGetLastError() != WSAEWOULDBLOCK)
GetWinSockError(WSAGetLastError());
return;
}
pSockAddr = (struct sockaddr*)(&their_addr);
pNetComm = new NetServerClient(newClientSocket);
addr_size = sizeof their_addr;
if(bind(newClientSocket, pSockAddr, addr_size) != 0)
{
GetWinSockError(WSAGetLastError());
pNetComm->ShutDown();
return;
}
if (pSockAddr->sa_family == AF_INET)
{
pTempBuffer = &(((struct sockaddr_in*)pSockAddr)->sin_addr);
port = ((struct sockaddr_in*)pSockAddr)->sin_port;
}
else
{
pTempBuffer = &(((struct sockaddr_in6*)pSockAddr)->sin6_addr);
port = ((struct sockaddr_in6*)pSockAddr)->sin6_port;
}
inet_ntop(their_addr.ss_family, pTempBuffer, pIPAddress, sizeof pIPAddress);
_snprintf(pPort, 256, "%d", (unsigned int)port);
pNetComm->StartCommunication(pIPAddress, pPort);
this->m_vpClients.push_back(pNetComm);
And here is my client code:
addrinfo hints;
addrinfo* pAddrInfo;
unsigned long tempUL;
int error;
memset(&hints, 0, sizeof hints); // make sure the struct is empty
hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6
hints.ai_socktype = type;
error = getaddrinfo(pIPAddress, pPort, &hints, &pAddrInfo);
if(error != 0)
{
GetWinSockError(error);
return;
}
for(pAddrInfo = pAddrInfo; pAddrInfo != NULL; pAddrInfo = pAddrInfo->ai_next)
{
this->m_Socket = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, pAddrInfo->ai_protocol);
if(connect(this->m_Socket, pAddrInfo->ai_addr, pAddrInfo->ai_addrlen) != 0)
continue;
break;
}
if(!pAddrInfo)
{
GetWinSockError(WSAGetLastError());
freeaddrinfo(pAddrInfo);
this->ShutDown();
return;
}
this->SetState(NET_COMM_STATE__READY);
freeaddrinfo(pAddrInfo);
The problem is that connect on the client always fails. I get the error "WSAECONNREFUSED: Connection refused".
I am pretty certain the reason my connection fails is because my client is not passing the correct IP address to getaddrinfo. When I run my server, I output the IP and port of the server solution. Then I have my client solution call it's getaddrinfo with the same IP and port info. However, my server solution does not appear to be gathering the correct IP and port info. It always tell me it's IP is either 0.0.0.0 (IPv4) or :: (IPv6). I don't understand how I get the proper IP for my client to connect to my server.
I have read these posts Getting server ip 0.0.0.0:0 from getaddrinfo() and sin_port returned in getaddrinfo wrong already and tried their solutions, but they didn't work for me.
Any help would be much appreciated.