Search code examples
pythoncraspberry-piudpclient

UDP Client-Server translation from Python to C


I am currently working on sending and receiving a message via UDP client-server relationship, where a raspberry pi is the client sending a message to a PC. I've been trying to translate the following python code for this (which works) into C, but it's unclear where the error in my code is. As you can see, the C output only has the first few elements of the message, and doesn't accurately show the message that is being sent. Thanks! The working Python code:

import socket

UDP_IP = "169.254.0.1"
UDP_PORT = 36112

#RBP Commands 

#MESSAGE = '01 01 4c 30 73 01'; #Set for remote mode
#MESSAGE = '01 01 4c 30 73 00'; #Clear remote mode
#MESSAGE = '01 00 4C 31' #Get module info
MESSAGE = '01 01 4C 53 73 00 43 00 00 01 2c 00 00 00 00 00 00 00 00' #Send Setpoint
#MESSAGE = '01 01 4C 52 18' #Set run state to run
#MESSAGE = '01 01 4C 52 02' #Set run state to stop

print("UDP target IP:", UDP_IP)
print("UDP target port:", UDP_PORT)
print("message:", MESSAGE)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.sendto(bytes.fromhex(MESSAGE), (UDP_IP, UDP_PORT))


while True:
    data, addr = sock.recvfrom(255)
    print("received message:", data.hex())
    exit();

output: outputs the message that was sent C code:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdint.h>
#include <unistd.h>
int main(void){
    int socket_desc;
    struct sockaddr_in server_addr;
    char server_message[60];
    
    uint8_t client_message[]= {0x01, 0x01, 0x4C, 0x53, 0x73, 0x00, 0x43, 0x00, 0x00, 0x01, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // send setpoint
    
    int server_struct_length = sizeof(server_addr);
    
    // Clean buffers:
    memset(server_message, '\0', sizeof(server_message));
    //memset(client_message, '\0', sizeof(client_message));

    // Create socket:
    socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    if(socket_desc < 0){
        printf("Error while creating socket\n");
        return -1;
    }
    printf("Socket created successfully\n");

    // Set port and IP:
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(36112);
    server_addr.sin_addr.s_addr = inet_addr("169.254.0.1");
    
    printf("Sending message:");// changed all the variables in for loops to be local to those loops ***********************
    printf("\n");
    for(uint16_t i=0; i<sizeof(client_message); i++){
        if(i%15 == 0){
            printf("\n");
            printf("0x%X\t", client_message[i]);
        }
    }
    // Send the message to server:
    if(sendto(socket_desc, client_message, strlen(client_message), 0, (struct sockaddr*)&server_addr, server_struct_length) < 0){
        printf("Unable to send message\n");
        return -1;
    }

    // Receive the server's response:
    if(recvfrom(socket_desc, server_message, sizeof(server_message), 0, (struct sockaddr*)&server_addr, &server_struct_length) < 0){
        printf("Error while receiving server's msg\n");
        return -1;
    }

    printf("\nReceived message:");
    for(uint16_t i=0; i<sizeof(server_message); i++){
        if(i%15 == 0)
            printf("\n");
        printf("0x%X\t", server_message[i]);
    }
    printf("\n");
    // Close the socket:
    close(socket_desc);

    return 0;
}

output: outputs message sent and message received


Solution

  • if(sendto(socket_desc, client_message, strlen(client_message), 0, ...
                                           ^^^^^^^
    

    You only send strlen(client_message) data, which is not the full size of the client message. A string in C is terminated by \0, so the length of the string is determined on the position of the first \0. Only, your message contains several \0 inside, so it is not actually a string and string functions should not be used on it. Use sizeof(client_message) instead.