Reputation: 1021
Working on updating my application that uses sockets to communicate from a python to a C program to use fixed length headers as a protocol when sending messages.
As an test example of my C Client code:
/*
Socket definition code put inside here
*/
char test2[] = "hello this is a test";
uint32_t test = sizeof(test2); //Get size of message and store in 32bit int
uint32_t test_conv = htonl(test); //Convert to network byte order
header = send(ConnectSocket, &test_conv, sizeof(uint32_t), 0); //Send size of message
body = send(ConnectSocket, test2, sizeof(test2), 0); //Send the actual message
Here is excerpt of python server code:
msg = clientsocket.recv(4)
msg_length = int.from_bytes(msg, sys.byteorder) //Get the header with the message length
msg_length = socket.ntohl(msg_length)
if len(msg) > 0:
print(f"This message length: {test} ")
msg = clientsocket.recv(msg_length) //Get the message
if len(msg)>0:
print(f'Message is: {msg.decode("utf-8")}')
Server.py output:
The message length: 21
Message is: hello this is a test
I am omitting the socket headers and stuff as well as error checking to save space in this post.
Is this a safe way to go about using fixed length headers? I am not expecting a high amount of traffic and I would only be sending a sentence or two worth of information in each message.
My final question is why when calling send in C do I use '&test_conv' for the message parameter. Would that not just be sending the address value for the test_conv variable. Don't I need to send the actual message, not the address?
Thanks for any insight and please provide any links to resources if I should be using a different implementation.
Upvotes: 0
Views: 657
Reputation: 7187
It seems to me you should use network byte order, not host byte order.
Also, I believe send() and recv() are allowed to return early, without transmission of all that was requested - that's why they return lengths. Usually they will transmit all of your data and return the full length, but they aren't guaranteed to do so.
For python, I like my http://stromberg.dnsalias.org/~dstromberg/bufsock.html module. It takes care of resumption for you.
For C, I think people pretty much just use a while loop for each send() and recv().
Upvotes: 0
Reputation: 16920
Your solution relying on a fixed sized integer announcing the number
of bytes in the following message seems correct to me.
Just be sure to use consistently sizeof
and/or strlen()
for
the textual message in your actual program.
In your example, transmitting sizeof(text2)
bytes includes the
implicit '\0'
at the end of text2
; then the python string
which is build at reception contains this useless (invisible
but nevertheless present) null-byte as last char.
Concerning &test_conv
in send()
, you need to understand that
this system call only considers a sequence of bytes.
It does not know that these bytes consist in an integer.
That's why you provide the address of the first byte to be sent
(&test_conv
) and the number of bytes to be sent
(sizeof(uint32_t)
) starting from this address.
The receiver will obtain this exact same sequence of bytes an
interpret them as the memory representation of a 32-bit integer
(considering endianness of course).
Note that the struct
package in python could help dealing
with memory representation of integers and endianness.
Upvotes: 1