Jump to content
  • Advertisement
Sign in to follow this  
rholding2001

htonl, ntohl??? why two?

This topic is 5132 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

ok im trying to build a simple chat client that sends and recieves messages there are a few things i need it to do which i am stuck on. im using winsock and c++ ok on gametutorials there is a section of code that goes like this for sending messages // fix our byte ordering messageSize = htonl(messageSize); int sendError; if ((sendError = send(mySocket, (char*)&messageSize, sizeof(messageSize), 0)) == SOCKET_ERROR) { printf("Send Failed!\n"); } // re-fix our byte ordering messageSize = ntohl(messageSize); // send the actual message if ((sendError = send(mySocket, charbuffer, messageSize, 0)) == SOCKET_ERROR) { printf("Send Failed!\n"); } why would we use the byte ordering twice, i know they are different host to and network to, how do these work? the next thing i want to ask is 1. i need to delimit a string so it will check for a character that seperates a message from a server code eg ~USER~PASS for purley a login and ~MSG~hello there you lot. 2. I cant seem to loop correctly or recognise asynchronously that messages are coming in from the server. ATM my client accepts a message and then just quits. how can i remedy this. thanks for any help. Man this stuff is quite hard

Share this post


Link to post
Share on other sites
Advertisement
The code would be clearer if it just used a temporary, and used htonl() to convert messageSize to the temporary, and sent the temporary. The reason the code calls it twice, is that it "optimizes" space by re-using the messageSize variable both for the actual value, and for the network-swizzled version of the value.

It seems to me that the stuff you're having trouble with is not networking, as much as writing working software in general. For example, it's not clear to me that you know how to find out what's going wrong in your program on your own. Perhaps things would become easier if you started working on that, instead of starting in the networking end?

I suggest that, both to discover this usage, and to figure out what's wrong with your program, you put breakpoints at the beginning of your send function, and at the code that accepts new connections and messages in your program, then run it with the debugger. When you hit the breakpoint, step through the program, line by line, and inspect all the variables. This ought to show you what your program is doing in detail, which should lead to some insight into what's actually going wrong.

Share this post


Link to post
Share on other sites
oh yes, the client i have sends and recieves everything its supposed to but with the fact that i have to send a message to recieve a message.

the htons i just wanted an explanation into what it was doing. i understand its to do with byte ordering, am i to assume that its like a "send code this say" and "recieve code this way"?

the reason i ask is that my "message sent" is called twice. if i were to drop one which would i drop. in that case i should just get tod of my conformation note and turn a blind eye

im more concerned at the moment with getting the program to asynchronously recieve messages without having to send something first. Ive been looking at nonblocking ports but cant find anything that is at my level of understanding. does anyone understand the concept of nonblocking or knows a decent site that has slipped my googling.

thanks for the replys all the same

Share this post


Link to post
Share on other sites
Quote:
Original post by rholding2001
// fix our byte ordering
messageSize = htonl(messageSize);

int sendError;
if ((sendError = send(mySocket, (char*)&messageSize, sizeof(messageSize), 0)) == SOCKET_ERROR)
{
printf("Send Failed!\n");
}

// re-fix our byte ordering
messageSize = ntohl(messageSize);

// send the actual message
if ((sendError = send(mySocket, charbuffer, messageSize, 0)) == SOCKET_ERROR)
{
printf("Send Failed!\n");
}


why would we use the byte ordering twice, i know they are different host to and network to, how do these work?

So there are two byte orders. Network order and host order. Network order is always the same, but host order might be different on different hosts. Therefore, when you're sending integer values around, you need to send them in network order.

The first send operation sends the length of the message. It sends it in network byte order, for the reason explained above.

The second send operation sends the message itself. It needs to know the length of the message, and for that it needs to convert the length back into host order.

Note, however, that the example code has a couple of significant flaws.

The most obvious is that it doesn't stop trying to send data when it fails.

The least obvious is that just as you need to convert to a known integer byte order to portably send data to another computer, you need to convert to a known integer size. sizeof(messageSize) may usually be 4 (assuming messageSize is an int0), but it might not be.

// Get the message size in network-order.
int noMessageSize = htonl(messageSize);
// We only send the first 4 bytes. Because network-order is big-endian -- the most
// significant digit comes first -- we need to skip over the extra bytes.
// Suppose int is 64 bits:
// noMessageSize is 0x0000000000000008 (for an eight character message)
// We want to send 0x00000008,
// so we need to move the pointer past the first four bytes.
if (SOCKET_ERROR == send(mySocket,
((char*)&noMessageSize) + (sizeof(noMessageSize) - 4), 4, 0))
throw "send error";
// Now send the message itself.
if (SOCKET_ERROR == send(mySocket, charbuffer, messageSize, 0))
throw "send error";




[edit]
If your compiler is up-to-date, this should work:

// Somewhere above...
#include <stdint.h>
// Get the message size in network-order.
uint32_t noMessageSize = htonl(messageSize);
if (SOCKET_ERROR == send(mySocket, (char*)&noMessageSize, 4, 0))
throw "send error";
// Now send the message itself.
if (SOCKET_ERROR == send(mySocket, charbuffer, messageSize, 0))
throw "send error";



uint32_t is a C99-specified typedef that is the expected size. C++ doesn't appear to have such a typedef, so I won't guarantee that it'll work. But it's certainly much nicer. [smile]
[/edit]
Quote:

1. i need to delimit a string so it will check for a character that seperates a message from a server code eg ~USER~PASS for purley a login and ~MSG~hello there you lot.

I don't understand the question.
Quote:

2. I cant seem to loop correctly or recognise asynchronously that messages are coming in from the server. ATM my client accepts a message and then just quits. how can i remedy this.

The problem is most likely that you aren't using non-blocking IO. Blocking sockets will wait until data has arrived when you try reading from them. So you can't any more send data until you recieve some. In addition, if you're reading your outgoing messages from cin (rather than text box in a window, for example), that is also in blocking mode by default, and so you'll have to enter a message before you can get around to checking for input.

I found a quick overview of the difference between the two socket types here.

For documentation on how to put your socket into non-blocking mode, consult MSDN.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
what a response. points for u!!!!!

ok with the delimiting thing, we are sending the messages in this format ~msg~hello there people

were the ~ is the delimiter. this will say check for the "~"'s and recognise the server command msg in this case is send a message to the room the preceding string after that is the message and that will be put in the char buffer ya?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!