Serket
Serket

Reputation: 4475

How to send a string from a Python socket to a C socket?

I've tried sending a string from a Python socket to a C socket, but for some reason, when receiving the string in C, I had to receive 2 characters extra, which I think is a newline. Since I don't want a newline, and since I think that there's a much better way to do what I'm doing, how can I send a string from a Python socket to a C socket? Do I need to use the Python module ctypes? Thanks

This is the line I'm executing (in Python):

sock.send(bytes("FPUT", "utf-8"))

and in order to receive the entire message, I have to receive 6 characters in C. Here is the receiving code I tried before I noticed the error:

char* msghdr = (char*) malloc(4*sizeof(char));
recv(i, msghdr, 4, 0); //i is the socket

Upvotes: 0

Views: 886

Answers (1)

Thomas Jager
Thomas Jager

Reputation: 5264

C strings are null-terminated, meaning that there is a 0 ('\0') character that marks the end of the string. Without that character, you're using whatever happens to come next in memory as part of the string.

This means that every string buffer needs to be one larger than the actual string length. You're only transmitting the contents of the string, not the representation of a C string.

There are two options for adding the NUL character. You could add it on the Python side, and receive one more character on the C side, or keep the Python code the same and add the '\0' in C:


This code shows only changes to C

#define MSGHDR_SIZE 4

// ...

char* msghdr = malloc((MSGHDR_SIZE + 1) * sizeof(char));
ssize_t recv_result = recv(i, msghdr, MSGHDR_SIZE, 0);
if (recv_result == -1) {
    // Handle error
} else {
    msghdr[recv_result] = '\0';
}

Here, the number of actual received bytes is used as the index at which to add the NUL character, ensuring that the buffer is always a valid string.

I've also used a preprocessor macro MSGHDR_SIZE. This is generally considered to be good practice, avoiding "magic numbers".

Also, I removed the cast on the result of malloc. See Do I cast the result of malloc?.


This code shows adding the character in Python

sock.send(bytes("FPUT", "utf-8") + b'\0')
// Includes NUL character
#define MSGHDR_SIZE 5

// ...

char* msghdr = malloc(MSGHDR_SIZE * sizeof(char));
ssize_t recv_result = recv(i, msghdr, MSGHDR_SIZE, 0);
if (recv_result == -1) {
    // Handle error
} else {
    msghdr[recv_result] = '\0';
}

Also, you should be checking the result of malloc for failure.

Upvotes: 1

Related Questions