0

i'm trying to send a structure through a TCP socket here's my code :

#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 8080

typedef struct toto
{
    int a;
    char *str;
} toto_t;


int main(int argc, char const* argv[])
{
    int server_fd, new_socket, valread;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    toto_t toto;

    toto.str = strdup("Helloworld");
    toto.a = strlen(toto.str);
    // Creating socket file descriptor
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0))
        == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
 
    // Forcefully attaching socket to the port 8080
    if (setsockopt(server_fd, SOL_SOCKET,
                   SO_REUSEADDR, &opt,
                   sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
 
    // Forcefully attaching socket to the port 8080
    if (bind(server_fd, (struct sockaddr*)&address,
             sizeof(address))
        < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    if ((new_socket
         = accept(server_fd, (struct sockaddr*)&address,
                  (socklen_t*)&addrlen))
        < 0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }
    send(new_socket, &toto, 14, 0);
  // closing the connected socket
    close(new_socket);
  // closing the listening socket
    shutdown(server_fd, SHUT_RDWR);
    return 0;
}

client

// Client side C/C++ program to demonstrate Socket
// programming
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 8080

typedef struct toto
{
    int a;
    char *str;
} toto_t;

int main(int argc, char const* argv[])
{
    int sock = 0, valread, client_fd;
    struct sockaddr_in serv_addr;
    toto_t toto;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("\n Socket creation error \n");
        return -1;
    }
 
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
 
    // Convert IPv4 and IPv6 addresses from text to binary
    // form
    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)
        <= 0) {
        printf(
            "\nInvalid address/ Address not supported \n");
        return -1;
    }
 
    if ((client_fd
         = connect(sock, (struct sockaddr*)&serv_addr,
                   sizeof(serv_addr)))
        < 0) {
        printf("\nConnection Failed \n");
        return -1;
    }
    valread = read(sock, &toto, 14);
    printf("%d\n%s\n", toto.a, toto.str);
 
    // closing the connected socket
    close(client_fd);
    return 0;
}

here's what i got :

10
Segmentation fault (core dumped)

valgrind says :

Process terminating with default action of signal 11 (SIGSEGV)
==77831==  Access not within mapped region at address 0x557F7AB802A0
==77831==    at 0x4A3EE72: strlen (vg_replace_strmem.c:494)
==77831==    by 0x4CE3D14: __vfprintf_internal (vfprintf-internal.c:1688)
==77831==    by 0x4CCCD3E: printf (printf.c:33)
==77831==    by 0x109350: main (in /home/tristan/Epitech/YEP/testotot/client)
==77831==  If you believe this happened as a result of a stack
==77831==  overflow in your program's main thread (unlikely but
==77831==  possible), you can try to increase the size of the
==77831==  main thread stack using the --main-stacksize= flag.
==77831==  The main thread stack size used in this run was 8388608

i don't understand why i can't get the string but when i get the int i've tried to pragma pack / attribute(packed) my structs but it still doesn't work so i'm not sure it's the padding that is blocking me

  • Does this answer your question? [Serializing a class which contains a std::string](https://stackoverflow.com/questions/7046244/serializing-a-class-which-contains-a-stdstring) – Stephen Newell Jun 09 '22 at 11:44
  • 2
    When you call `send`, you're writing a literal address via `str`, not the string it points to. You're going to need to actually serialize the data properly. The linked duplicate is the exact same fundamental problem, just using C++ strings instead of `char*`. – Stephen Newell Jun 09 '22 at 11:44
  • Thanks i'll look into serialization ! and why not std::strings simply because i'm making this in C not C++ – GloutonBargeot Jun 09 '22 at 11:46
  • It's the same issue. std::string is a struct containing a pointer to the char data. – stark Jun 09 '22 at 11:50
  • Even if you are not passing pointers, use sizeof(toto) instead of what you think the size ought to be - you never know what the padding is like - the size of the structure may vary depending on alignment. – cup Jun 09 '22 at 11:57

0 Answers0