使用readv从套接字读取数据

时间:2016-05-14 16:05:44

标签: c sockets unix-socket

我在使用writev()/ readv()进行客户端 - 服务器通信时出现问题。

我有两个结构,headerdata定义如下:

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

服务器(简而言之):

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);

客户(简称):

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);

但客户端因为received[0].iov_baseNULL而导致段错误。为什么? 套接字已正确打开,客户端已正确连接到服务器。它是一个AF_UNIX套接字。

1 个答案:

答案 0 :(得分:1)

首先,在您的服务器代码中,您正在编写指针。这毫无意义。你不想通过网络传输指针。要传输字符串,您必须执行以下操作:

<SearchForm />

(您可能希望将字符串长度移动到消息头并保存向量的一个元素,并使协议更具可读性。)

其次,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; 不会为您分配内存,或者想要读取多少字节。正确初始化传递给readv的IO向量中的iov_baseiov_len是您的工作。为了读取动态分配的可变大小字符串,您可能希望读取两次。首先,读取包含字符串长度的消息的一部分,然后分配字符串,并读取消息的其余部分。