Sign in to follow this  
Thrust

Converting an int to a const char*

Recommended Posts

Hi, I am currenty trying to convert an int (a players coordniate in a game) into a const char so that I can send it using winsock. Here is the code:
ZeroMemory(buffer, 256);
strcpy(buffer,p1.y_pos);
send(connectSocket,buffer,strlen(buffer),0);
delete [] buffer;

where p1.y_pos is the players y position. I do not know how to convert it into a string/char. I am guessing something like p1.y_pos.c_str() but I dont think that will work. What should I do?

Share this post


Link to post
Share on other sites
Here's the way I would do it, using std::stringstream:

#include <string>
#include <sstream>

std::string IntToString(int value)
{
std::ostringstream converter;
converter << value;
return converter.str();
}



This function returns a std::string. To use it in the send function, try something like:

std::string buffer = IntToString(p1.y_pos);
send(connectSocket, buffer.c_str(), buffer.length(), 0);


The above has not been compiled, but should be correct (I hope).

Share this post


Link to post
Share on other sites
you don't need to put it in a string.

just do a type-cast:

i.e:


send(connectSocket,(const char*)&p1.y_pos,sizeof(p1.y_pos),0);






*edit*: D'OH... missed the 'address of' operator (&)

[Edited by - Madhed on February 9, 2005 5:17:05 PM]

Share this post


Link to post
Share on other sites
If you're using std::string this will work


std::ostringstream strstrm;
strstrm<<p1.y_pos;
send(connectSocket,strstrm.str(),strstrm.str().length(),0);

Share this post


Link to post
Share on other sites
Thank you all for your help. I used the type casting method I believe it was and it works. I do have a question though, how would I convert back a char to an int? Here is the code

//Recieve p2 y position
recv(connectSocket,buffer,256,0);
p2.y_pos = buffer;
delete [] buffer;
//



I tried type casting it as:
p2.y_pos = (int*)&buffer;
but it would not work. This is the last help I need I believe. Thank you

Share this post


Link to post
Share on other sites
Quote:
Original post by Madhed
send(connectSocket,(const char*)&p1.y_pos,strlen(buffer),0);


OK, I'm not familiar with that function, but I'm guessing you would need to do something like this (if it's anything like working with binary files)

send(connectSocket,(const char*)&p1.y_pos,sizeof(p1.y_pos),0)

Share this post


Link to post
Share on other sites
(edit: hum... was the last one...)

Hello,

1)The C++ way: use a string stream

#include <sstream>
std::stringstream ss;
ss << p1.y_pos << std::ends;
std::string str = ss.str();
send(connectSocket,str.c_str(),str.length()+1,0);


2) the C way: use sprintf() (not strcpy)

char buffer[16];
sprintf(buffer, "%d", p1.y_pos);
send(connectSocket,buffer,strlen(buffer)+1,0);

I added the +1 because I wanted to send the /0 character. If I don't then how would I know where my string ends?

A better solution should be to send the binary data directly:

send(connectSocket,&p1.y_pos,sizeof(p1.y_pos),0);

This is probably easier to manage and to read, and avoid a transformation to a string.

HTH,

Share this post


Link to post
Share on other sites
All the replies above are good, but if you're not using C++ or the STL, Madhed's reply is fine (although you want sizeof(int) rather than strlen(buffer), assuming y_pos is an int). Using stringstreams might be overkill for what you want.

Thinking of the const char* as a string isn't too helpful because it makes you think of text, but it's just being used here to denote generic data: you can take the address of any data and pass it to send, along with the length of the data.

EDIT: bah, I'm a slow poster :)

Share this post


Link to post
Share on other sites
Okay, for receiving the data you should take these steps:

1. You must know in what order you sent your data.
2. For every send() you do a recv() with the same data type

send(sock,(const char*)&bla,sizeof(int),0);
................
recv(sock2,(char*)&bla2,sizeof(int),0);

I know some people might want to kill me for oversimplifying this topic
but that's basically what you will be doing.

When you got it up and running you might want to address the topics of
serializing/deserializing, strucure padding, endianess and the like...

but don't get confused just play around a bit and when you think know
what's going on read about those things related to networking.

EDIT: I'm not sure, but /me thinks that recv() must get a (char*)
pfffft. damn winsock, unix is teh r0xxx0rs ;)

Share this post


Link to post
Share on other sites
I do understand sending and recieving data. My problem is I am trying to send a players coods back and fourth and I am having problems converting the cords back and fourth into chars to send them and recieve them. That is my only problem.


void hostData()
{
//Send p1 y position
ZeroMemory(buffer, 256);
strcpy(buffer,(const char*)&p1.y_pos);
send(connectSocket,buffer,strlen(buffer),0);
delete [] buffer;
//

//Recieve p2 y position
recv(connectSocket,buffer,256,0);
p2.y_pos = buffer;
delete [] buffer;
//

//Send p1 x position
ZeroMemory(buffer, 256);
strcpy(buffer,(const char*)&p1.x_pos);
send(connectSocket,buffer,strlen(buffer),0);
delete [] buffer;
//

//Recieve p2 x position
recv(connectSocket,buffer,256,0);
p2.x_pos = buffer;
delete [] buffer;
//
}

void joinData()
{
//Recieve p1 y position
recv(connectSocket,buffer,256,0);
p2.y_pos = buffer;
delete [] buffer;
//

//Send p2 y position
ZeroMemory(buffer, 256);
strcpy(buffer,(const char*)&p1.y_pos);
send(connectSocket,buffer,strlen(buffer),0);
delete [] buffer;
//

//Recieve p1 x position
recv(connectSocket,buffer,256,0);
p2.x_pos = buffer;
delete [] buffer;
//

//Send p2 x position
ZeroMemory(buffer, 256);
strcpy(buffer,(const char*)&p1.x_pos);
send(connectSocket,buffer,strlen(buffer),0);
delete [] buffer;
//
}


I am testing it right now, I havent even gotten it to compile. In my theory it should work, and I do not want to know if it will or wont, I learn by trying to fix it. What I would like to know is with this:


//Recieve p1 x position
recv(connectSocket,buffer,256,0);
p2.x_pos = buffer;
delete [] buffer;
//



I do not know how to convert the buffer back into an int to make it the p2.x_pos. That is my only problem at this moment.

Share this post


Link to post
Share on other sites
[edit] Wow, did everyone edit their posts at once... [lol] [/edit]

Let's say you had this
 int location = 25; 
and you wanted to make it into a string. Here is one method -

char buffer[256];
memset(buffer,0,256);
sprintf(buffer,"%i",location);

Now it is stored in the buffer, so you can send it. Let's say you receieve a buffer that containts the int, but it is in char format, you can do this:

int newlocation = atoi(buffer);

That will convert the integer represented in buffer into an integer and store it into newlocation.

This is just a quick and dirty sample using C-styled code. There are definitly better and safer ways, but if you know what you are going to be doing, this will be fine.

So your new code:

char buffer[256];
void hostData()
{
//Send p1 y position
memset(buffer,0,256);
sprintf(buffer,"%i",p1.y_pos);
send(connectSocket,buffer,strlen(buffer),0);

//Recieve p2 y position
memset(buffer,0,256);
recv(connectSocket,buffer,256,0);
p2.y_pos = atoi(buffer);

...
}





Notice you do not need to delete the buffer! I hope this helps. It should compile as is, but you need to include <string.h> for memset and <stdio.h> for sprintf. atoi is in <stdlib.h>

- Drew

Share this post


Link to post
Share on other sites
It doesent tell me how to convert a char into an int, which is all im looking for. I did take your advice into consideration though.

Share this post


Link to post
Share on other sites
Gratzi Benton. It compiles, and no warnings like before. Thank you very much all for your help, now make with the positive ratings on me! j/k

Share this post


Link to post
Share on other sites
you're actually not converting a char to an int.
to do that you'd just write:

int a;
char b = 5;
a = b;

you are trying to extract data from an array of chars to an int.

So either you use recv(sock,(char*)&data,sizeof(int),0);
like I told you in my previous post.

or you could use:

char buffer[512];
int a = *(int*)&buffer[0];

I'd go for the recv() variant.

Share this post


Link to post
Share on other sites
Quote:
It compiles, and no warnings like before


How did you do it? Just curious.

Because strange things could happen if you treat your buffer like
a string.
If you don't clear the array with zeroes before recv()'ing data
you might end up with a segmentation fault because you string
never seems to end.
Or what happens if the receiver is a bit lame and two send()s are
made before the recv() is called. You would either end up with one
string made up of those two send()s or you just read one value
and the second is discarded..... =( very bad

Share this post


Link to post
Share on other sites
<code>
#include <string.h>

memset(buffer, 0, 256);
strncpy(buffer, (char*) &(p1.y_pos), sizeof(int));
send(connectSocket,buffer, sizeof(int), 0);
// strlen() dont work. Probably strlen() will return 0.
// you may send a fixed number of bytes as a protocol or the first x bytes indicating the size of the message, or etc

........


recv(connectSocket,buffer,sizeof(int),0);
strncpy((char*) &(p2.y_pos), buffer, sizeof(int))

</code>

[]'s
Sassá

Share this post


Link to post
Share on other sites
There is actuially something wrong with the code. This is the code:



void hostData()
{
//Send p1 y position
sprintf(buffer,"%i",p1.y_pos);
send(connectSocket,buffer,strlen(buffer),0);
cout<<"p1.y_pos"<<endl;
cout<<p1.y_pos<<endl;

//Recieve p2 y position
recv(connectSocket,buffer,256,0);
p2.y_pos = atoi(buffer);
cout<<"p2.y_pos"<<endl;
cout<<p2.y_pos<<endl;

//Send p1 x position
sprintf(buffer,"%i",p1.x_pos);
send(connectSocket,buffer,strlen(buffer),0);
cout<<"p1.x_pos"<<endl;
cout<<p1.x_pos<<endl;

//Recieve p2 x position
recv(connectSocket,buffer,256,0);
p2.x_pos = atoi(buffer);
cout<<"p2.x_pos"<<endl;
cout<<p2.x_pos<<endl;

}

void joinData()
{
//Recieve p2 y position
recv(connectSocket,buffer,256,0);
p2.y_pos = atoi(buffer);
cout<<"p2.y_pos"<<endl;
cout<<p2.y_pos<<endl;

//Send p1 y position
sprintf(buffer,"%i",p1.y_pos);
send(connectSocket,buffer,strlen(buffer),0);
cout<<"p1.y_pos"<<endl;
cout<<p1.y_pos<<endl;

//Recieve p2 x position
recv(connectSocket,buffer,256,0);
p2.x_pos = atoi(buffer);
cout<<"p2.x_pos"<<endl;
cout<<p2.x_pos<<endl;

//Send p1 x position
sprintf(buffer,"%i",p1.x_pos);
send(connectSocket,buffer,strlen(buffer),0);
cout<<"p1.x_pos"<<endl;
cout<<p1.x_pos<<endl;



}



For some reason it says it sends it but it never gets recieved. It gets recieved as a zero. Here look at the stdout file it gives off:


Winsock initialized...
Socket created...
Connected
p1.y_pos
414
p2.y_pos
414
p1.x_pos
394
p2.x_pos
394
p1.y_pos
414
p2.y_pos
414
p1.x_pos
394
p2.x_pos
394
p1.y_pos
414
p2.y_pos
414
p1.x_pos
394
p2.x_pos
394
p1.y_pos
414
p2.y_pos
414
etc...



Unfortunatly I cannot figure it out. It seems to change the p1 x and y to the p2 one for the host function and it goes in opposite directions on the join function for gameplay. Its really weird and I spent about 2 hrs last night trying to figure it out, but still no success.

Share this post


Link to post
Share on other sites
You say it seems that p1 and p2 position get exchanged?
My explanation would be (assuming that you use TCP not UDP)
that data is arriving too fast for the receiver to pick up:

TCP is a stream based connection approach.
Multiple sends don't need to result in multiple recvs.

if you do this: (pseudocode)


send("123"); //p1 pos
send("111"); //p2 pos
send("126"); //p1 pos
send("115"); //p2 pos

this is sent across the wire: "123111126115"

you might receive something like that:
recv(buffer); // buffer = "12311" (p1 pos + first number of p2 pos)
recv(buffer); // buffer = "1126115" (the rest of the stream)



you really need to do more to seperate your data in the stream.
ALWAYS REMEMBER: TCP sockets are stream oriented. the receiver
only gets a bunch of bytes that he must take care of himself.

Share this post


Link to post
Share on other sites
How would I go about fixing this? I can PM you the whole code if you would like, although it is 1300+ lines long :). With the code I have there what can I do to solve this problem? This is my first time sending/recieving. I mostly understand the theory.


//--------------------------------------------//
//Onliene Functions//
//--------------------------------------------//

//Hosts a game
void host()
{
int error;
//loads winsock
WSADATA wsaData;
error = WSAStartup(MAKEWORD(2, 0), &wsaData);

//error handler
if (error != 0)
{
cout << "Couldn't Initialize Winsock: 1" << endl;
// unload WinSock
WSACleanup ();
return;
}

cout << "Winsock initialized..." << endl;

//creates a socket
connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

//error handler
if (connectSocket == INVALID_SOCKET)
{
cout << "Couldnt create socket: 2" << endl;
// unload WinSock
WSACleanup ();
return;
}

cout << "Socket created..." << endl;

//This is the port it connects to, we are using 12521
int port = 12521;
// the address structure for a TCP socket
sockaddr_in addr;

addr.sin_family = AF_INET; // Address family Internet
addr.sin_port = htons (port); // Assign port to this socket
addr.sin_addr.s_addr = htonl (INADDR_ANY); // No destination

if (bind(connectSocket, (LPSOCKADDR)&addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
cout << "Couldn't bind socket: 3" << endl;
// unload WinSock
WSACleanup ();
return;
}

cout << "Socket binded..." << endl;

//Waits for the connection
cout << "Waiting for connection from other player..." << endl;
SFont_Write(Connectmenu, Font, 5,145,"Waiting for connection from other player...");
SDL_Flip(Connectmenu);
listen(connectSocket, 1);

//Socket for connection
SOCKET connectPlayer;

connectPlayer = accept(connectSocket, NULL, NULL);
cout << "Client accepted... SUCCESS!" << endl;

p1.connected = true;
SFont_Write(Connectmenu, Font, 5,160,"CONNECTED!!!");
SDL_Flip(Connectmenu);
}


//Joins a game
void join()
{
int error;
bool isRunning = true;
Uint8* keys;
getInput();
ipAddress = text;
text = "";
cout<<"Woot!"<<endl;

//loads winsock
WSADATA wsaData;
error = WSAStartup(MAKEWORD(2, 0), &wsaData);

//error handler
if (error != 0)
{
cout << "Couldn't Initialize Winsock: 1" << endl;
// unload WinSock
WSACleanup ();
return;
}

cout << "Winsock initialized..." << endl;

//Stores information about the hosting player
LPHOSTENT hostEntry;
in_addr iaHost;
//Hosts IP address
iaHost.s_addr = inet_addr(ipAddress.c_str());
//Gathers information using the IP address
hostEntry = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr), AF_INET);
//error handling
if (!hostEntry)
{
cout << "Error gathering data..." << endl;
WSACleanup ();
return;
}



//Creates socket
connectSocket = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);

//error handler
if (connectSocket == INVALID_SOCKET)
{
cout << "Couldnt create socket: 2" << endl;
// unload WinSock
WSACleanup ();
return;
}

cout << "Socket created..." << endl;

//This is the port it connects to, we are using 12521
const int port = 12521;
// the address structure for a TCP socket
sockaddr_in serverInfo;

// Address family Internet
serverInfo.sin_family = AF_INET;

serverInfo.sin_port = htons (port); // Assign port to this socket

serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list); // Hosts IP address


//Connects to the host
error = connect(connectSocket,(LPSOCKADDR)&serverInfo,sizeof(struct sockaddr));

//error handler
if (error != 0)
{
cout << "Couldn't connect to host: 3" << endl;
// unload WinSock
WSACleanup ();
return;
}

cout << "Connected" << endl;
p1.connected = true;
SFont_Write(Connectmenu, Font, 5,160,"CONNECTED!");
SDL_Flip(Connectmenu);

}

void hostData()
{
//Send p1 y position
sprintf(buffer,"%i",p1.y_pos);
send(connectSocket,buffer,strlen(buffer),0);
cout<<"p1.y_pos"<<endl;
cout<<p1.y_pos<<endl;

//Recieve p2 y position
recv(connectSocket,buffer,256,0);
p2.y_pos = atoi(buffer);
cout<<"p2.y_pos"<<endl;
cout<<p2.y_pos<<endl;

//Send p1 x position
sprintf(buffer,"%i",p1.x_pos);
send(connectSocket,buffer,strlen(buffer),0);
cout<<"p1.x_pos"<<endl;
cout<<p1.x_pos<<endl;

//Recieve p2 x position
recv(connectSocket,buffer,256,0);
p2.x_pos = atoi(buffer);
cout<<"p2.x_pos"<<endl;
cout<<p2.x_pos<<endl;

}

void joinData()
{
//Recieve p2 y position
recv(connectSocket,buffer,256,0);
p2.y_pos = atoi(buffer);
cout<<"p2.y_pos"<<endl;
cout<<p2.y_pos<<endl;

//Send p1 y position
sprintf(buffer,"%i",p1.y_pos);
send(connectSocket,buffer,strlen(buffer),0);
cout<<"p1.y_pos"<<endl;
cout<<p1.y_pos<<endl;

//Recieve p2 x position
recv(connectSocket,buffer,256,0);
p2.x_pos = atoi(buffer);
cout<<"p2.x_pos"<<endl;
cout<<p2.x_pos<<endl;

//Send p1 x position
sprintf(buffer,"%i",p1.x_pos);
send(connectSocket,buffer,strlen(buffer),0);
cout<<"p1.x_pos"<<endl;
cout<<p1.x_pos<<endl;
}

Share this post


Link to post
Share on other sites
Since this is for networking, you should not be converting integers to character arrays, that would often make them bigger than just integers, and make them variable length instead of fixed.
You thought you had to do this because the function takes a const char *, but this is does not mean you are supposed to send everything as text. Doing so would mean lots of extra work at the other end to parse the incomming data.

Since the function is not templated, the parameter had to be of some type, something had to be chosen. 'const char *', merely means a pointer to the first byte of data, which It's not going to modify. So all you have to do is give it a pointer to the first byte of data you want to send. You also unfortunately have to tell it that your data is an array of chars.
Madhed's earlier examples were showing you the easy and right way to do it, as binary.

You only need to do the exact same thing you already do on this line:
  hostEntry = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr), AF_INET);
(The words const and struct aren't needed in there btw)

Share this post


Link to post
Share on other sites
Thank you for your help everyone, I almost have it. I updated the code like madheds* examples:


void hostData()
{
//Send p1 y position
send(connectSocket,(const char*)&p1.y_pos,sizeof(p1.y_pos),0);
cout<<"p1.y_pos"<<endl;
cout<<p1.y_pos<<endl;

//Recieve p2 y position
recv(connectSocket,(char*)&p2.y_pos,sizeof(p2.y_pos),0);
cout<<"p2.y_pos"<<endl;
cout<<p2.y_pos<<endl;

//Send p1 x position
send(connectSocket,(const char*)&p1.x_pos,sizeof(p1.x_pos),0);
cout<<"p1.x_pos"<<endl;
cout<<p1.x_pos<<endl;

//Recieve p2 x position
recv(connectSocket,(char*)&p2.x_pos,sizeof(p2.x_pos),0);
cout<<"p2.x_pos"<<endl;
cout<<p2.x_pos<<endl;

}

void joinData()
{
//Recieve p2 y position
recv(connectSocket,(char*)&p2.y_pos,sizeof(p2.y_pos),0);
cout<<"p2.y_pos"<<endl;
cout<<p2.y_pos<<endl;

//Send p1 y position
send(connectSocket,(const char*)&p1.y_pos,sizeof(p1.y_pos),0);
cout<<"p1.y_pos"<<endl;
cout<<p1.y_pos<<endl;

//Recieve p2 x position
recv(connectSocket,(char*)&p2.x_pos,sizeof(p2.x_pos),0);
cout<<"p2.x_pos"<<endl;
cout<<p2.x_pos<<endl;

//Send p1 x position
send(connectSocket,(const char*)&p1.x_pos,sizeof(p1.x_pos),0);
cout<<"p1.x_pos"<<endl;
cout<<p1.x_pos<<endl;
}



but now it still says I am not recieving the xpos or the ypos.

Winsock initialized...
Socket created...
Connected
p2.y_pos
0
p1.y_pos
414
p2.x_pos
0
p1.x_pos
394


There has to be something wrong with either the way it is being sent or recieved. Hmmm, once this actuially works im going to spend a good day just looking it over and figuring out how it works so I dont have this problem again. I always run into problems like this when I try something new. Ironically when I made my first winsock program I had no problems, now I cant get it to work at all.

Share this post


Link to post
Share on other sites
The send/recv calls you have now look correct.

You'll want to check the return values of your send/recv call. If that recv is returning an error (-1), then you didn't receive anything, which might explain why it's printing 0 for the value (assuming you initialized it to 0).

For example, if you set the socket in a nonblocking mode, your recv calls will return -1, with the error code set to EAGAIN, meaning you should try the receive again because there's currently no data available.

The way your code is now, you want it to be in blocking mode, so recv won't return until it actually gets some data, or the connection breaks.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this