lmurdock12
lmurdock12

Reputation: 1021

Fixed Length Socket communication from python to C

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

Answers (2)

dstromberg
dstromberg

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

prog-fh
prog-fh

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

Related Questions