简体   繁体   中英

Reading data from socket with readv

I'm having problems with a client-server communication made with writev()/readv().

I have two struct, header and data defined like this:

typedef struct {
    int op;
    int key;
} message_hdr_t;
typedef struct {
    int len;
    char *data;
} message_data_t;

The server does (in short):

message_hdr_t h = {1, 11};
message_data_t d;
d.len = 3;
strcpy(d.data, "msg");

struct iovec tosend[2];
tosend[0].iov_base = &h;
tosend[0].iov_len = sizeof(message_hdr_t);
tosend[1].iov_base = &d;
tosend[1].iov_len = sizeof(message_data_t);

writev(socket, tosend, 2);
close(socket);

The client (in short):

struct iovec received[2];
readv(socket, received, 2);
message_hdr_t header;
header.op = ((message_hdr_t *) received[0].iov_base)->op;
header.key = ((message_hdr_t *) received[0].iov_base)->key;
printf("Received op: %i, key: %i\n",header.op,header.key;
close(socket);

But the client gets a segfault because received[0].iov_base is NULL . Why? The socket is correctly opened and the client is correctly connected to the server. It's an AF_UNIX socket.

First, in your server code, you are writing a pointer . This makes no sense. You don't want to transmit pointers over the wire. To transmit a string, you have to do something like this:

char* message = ...;
message_hdr_t h = {1, 11};

uint32_t message_length = strlen(message);

struct iovec tosend[3];

tosend[0].iov_base = &h;
tosend[0].iov_len = sizeof(message_hdr_t);

tosend[1].iov_base = &message_length;
tosend[1].iov_len = sizeof(message_length);

tosend[2].iov_base = message;
tosend[2].iov_len = message_length;

(You may want to move the string length to the message header and save one element of the vector, and make the protocol more readable).

Second, readv won't allocate memory for you, or divine out how many bytes you want to read. It's your job to correctly initialize iov_base and iov_len in the IO vector passed to readv . In order to read a dynamically-allocated variable-size string, you probably want to read twice. First, read a part of the message that contains the length of the string, then allocate the string, and read the rest of the message.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM