user2616248
user2616248

Reputation: 41

Structure issue and int to char* conversion

In my first program I find a local ip address (int iip) and what I would like to do is send that ip address as well as the port (int port = 1100) in a structure (Ins c). Then I would like the second program to receive this structure and pick out the ip address and port to use in a tcp connection later on.

n_addr inaddr;
inaddr.s_addr = htonl(iip);

    int udp_socket_info;
    struct sockaddr_in udp_server;

    udp_socket_info = socket(AF_INET, SOCK_DGRAM, 0);
    if (udp_socket_info == -1) {
    puts("Could not create udp socket");
    }
    puts("Udp socket created");

    udp_server.sin_addr.s_addr = inet_addr("225.0.0.37"); 
    udp_server.sin_port = htons(1100);
    udp_server.sin_family = AF_INET;

    int port = 1100;


 Ins c(iip, port);        
 sendto(udp_socket_info, &c, sizeof(c), 0, (struct sockaddr *)&udp_server, sizeof(udp_server));
puts("STRUCT Message Sent");

In one program I am receiving the following structure:

Ins c;
if (recvfrom(udp_socket_info, &c, sizeof(c), 0, &addr, &fromlen) < 0) {
perror("Recvfrom error:");
}
puts("STRUCT Message Received");

tcp_ip = c.address;
tcp_port = c.port;

In the header file MonReqServer.hh I declare tcp_ip and tcp_port as char* because that is what I need to use to setup the tcp socket.

 private:
   char* tcp_ip;
   char* tcp_port;

And the following is the header for Ins.hh

namespace Pds {
class Ins
  {
  public:
    Ins();
    enum Option {DoNotInitialize};
    explicit Ins(Option);
    explicit Ins(unsigned short port);
    explicit Ins(int address);
    Ins(int address, unsigned short port);
    Ins(const Ins& ins, unsigned short port);
    explicit Ins(const sockaddr_in& sa);

    int                   address()     const; 
    void                  address(int address);
    unsigned short        portId()      const; 

    int operator==(const Ins& that)  const;

  protected:
    int      _address;
    unsigned _port;
  };
}

These are my errors:

MonReqServer.cc: In member function 'virtual void Pds::MonReqServer::routine()':
MonReqServer.cc:79: error: cannot resolve overloaded function 'address' based on conversion to type 'char*'
MonReqServer.cc:80: error: 'class Pds::Ins' has no member named 'port'

My question then is how do I convert my address into a char* once I receive it? Specifically what is the command to switch from int to char* and how do I impliment it? Also why does it say Ins has no member named port? I thought an ip address and a port are what Ins is meant to take? Please let me know if my questions are unclear or if you need any other information? Thank you!

Upvotes: 0

Views: 295

Answers (2)

user4581301
user4581301

Reputation: 33952

First off, danger danger!

char* tcp_ip;
char* tcp_port;

These pointers need to point to something, and it has to be something with a measure of permanence. I don't see this as likely to happen, so you should define the storage here.

char tcp_ip[SizeOfBiggestIPAddressPossible];
char tcp_port[SizeOfBiggestPortNumberPossible];

where

#define     SizeOfBiggestIPAddressPossible (4+1+4+1+4+1+4+1+4+1+4+1+4+1+4+1)
#define     SizeOfBiggestPortNumberPossible (5+1)

But this is just stupid. Since OP tagged for C++, let's just use a couple strings and save us the trouble of buffer overflows and other weirds.

std::string tcp_ip;
std::string tcp_port;

Next, changing a number into a string is half worthless here. Number to string works for the port number...

tcp_port = std::to_string(c.portId());

Or if lacking C++11 support create the following function

template <class TYPE>
std::string toString(TYPE val)
{
    std::stringstream temp;
    temp << val;
    return  temp.str();
}

and call it

tcp_port = toString(c.portId());

but to convert a number to an IP address is another beast entirely. the IP address is a formatted string with dots or colons intermixed with numbers. If there is a good C++ way to do this, I don't know it.

In *nux land, you call inet_ntop.

Assuming Ipv4 (not compiled and tested, but should be close):

char temp[INET_ADDRSTRLEN];
struct sockaddr_in sockAddr;
sockAddr.sin_addr.S_un.S_addr = htonl(c.address());
if (inet_ntop(AF_INET, &addr, temp, INET_ADDRSTRLEN)!= null)
{
    tcp_ip = temp;
}
else
{
    std::cerr << "Bad address" << std::endl;
    // handle error
}

In Windows you can call the same function or a whole raft of Windows-specific alternatives.

You now have two nice, polite C++ strings doing all of the memory management heavy lifting for you. To get C style strings (const char *) back use the c_str method.

const char * addrp = c.address().c_str();

If you need a non const char * someone deserves a slap.

edit: Missed out on the obvious IP4 only hack

This will get you the address as a string, but it doesn't support the future. Or the past as IPv6 has been around for what, 35 years?

uint32_t temp = c.address(); 
std::stringstream addr;
addr << ((temp >> 24) & 0xFF) << '.' <<
        ((temp >> 16) & 0xFF) << '.' <<
        ((temp >>  8) & 0xFF) << '.' <<
        ((temp >>  0) & 0xFF);
tcp_ip = addr.str();

Upvotes: 1

EvgeniyZh
EvgeniyZh

Reputation: 905

First of all your members are called _port and _address and not port and address. They are not public, so you can obtain them with your functions portId() and address() Second, to convert number to c string, you can use sprintf or itoa functions.

Upvotes: 0

Related Questions