簡體   English   中英

使用 readv 從套接字讀取數據

[英]Reading data from socket with readv

我在使用 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 套接字。

首先,在您的服務器代碼中,您正在編寫一個指針 這沒有任何意義。 您不想通過線路傳輸指針。 要傳輸字符串,您必須執行以下操作:

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不會為您分配內存,也不會算出您要讀取的字節數。 這是你的工作,以正確初始化iov_baseiov_len在IO載體傳遞給readv 為了讀取動態分配的可變大小字符串,您可能需要讀取兩次。 首先,讀取包含字符串長度的消息的一部分,然后分配字符串,並讀取消息的其余部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM