我正在编写一个使用 AF_UNIX 套接字的客户端-服务器应用程序。 客户端生成一个字符串,然后在发送 header 后将其发送到套接字上。然后服务器读取 header ,为字符串分配空间,然后读取字符串。
header 定义为:
typedef struct {
unsigned long key;
op_t op; // op_t is an enum
} header_t;
字符串及其长度被存储:
typedef struct {
unsigned int len;
char* buf;
} data_t;
还有另一个结构将这两个东西组合成一个(不是我的选择,我必须按原样使用这些东西)。
typedef struct {
header_t hdr;
data_t data;
} message_t;
我正在使用 writev()
系统调用通过套接字发送数据,如下所示:
int sendRequest(long fd, message_t *msg) {
struct iovec to_send[3];
/* Header */
to_send[0].iov_base = &(msg->hdr);
to_send[0].iov_len = sizeof(header_t);
/* Data */
to_send[1].iov_base = &(msg->data.len);
to_send[1].iov_len = sizeof(msg->data.len);
to_send[2].iov_base = msg->data.buf;
to_send[2].iov_len = msg->data.len;
int c;
if((c = writev(fd, to_send, (msg->data.len > 0) ? 3 : 2)) < 0) {
return -1;
}
printf("#### %i BYTES WRITTEN (header: %i) ####\n",c, to_send[0].iov_len);
return 0;
}
为了读取,我使用两个不同的函数,一个用于读取标题,一个用于读取数据:
int readHeader(long fd, header_t *hdr) {
struct iovec to_read[1];
to_read[0].iov_base = hdr;
to_read[0].iov_len = sizeof(header_t);
errno = 0;
int c;
if((c = readv(fd, to_read, 1)) <= 0) {
return -1;
}
printf("[H] %i BYTES READ \n",c);
return 0;
}
int readData(long fd, data_t *data) {
struct iovec to_read[2];
/* First, read how long is the buffer */
to_read[0].iov_base = &(data->len);
to_read[0].iov_len = sizeof(data->len);
int c;
if((errno = 0, c = readv(fd, to_read, 1)) <= 0)
return -1;
if(data->len > 0) {
data->buf = calloc(data->len, sizeof(char));
if(data->buf == NULL)
return -1;
/* Read the string */
to_read[1].iov_base = data->buf;
to_read[1].iov_len = data->len;
if((errno = 0, c += readv(fd, &to_read[1], 1)) <= 0) {
free(data->buf);
return -1;
}
}
else {
data->buf = NULL;
}
printf("[D] %i BYTES READ (%i + %i)",c, to_read[0].iov_len, to_read[1].iov_len);
return 0;
}
问题来了。
如果我发送一个 8193 字节长的字符串,则客户端上一切正常,输出
写入 8213 字节( header :16)
这是正确的,因为 16 个字节来自 header ,4 个字节来自 len
字段,8193 来自字符串。
但服务器打印出这样的信息:
[H] 16 字节读取
(好的),然后[D] 8176 字节读取
(错误!)。因此,还剩 21 个字节可供读取。为什么?如果我尝试发送长度为 8192 或更短的字符串,则一切正常。假设 readv() 可以读取的字节数有限制,那么读取所写入的所有内容的正确方法是什么?
最佳答案
what is the correct way to read everything that was written?
不保证 readv 会立即返回所有数据。如果第一次读取没有返回所有请求的字节,那么您需要再次调用 read/readv 来获取其余的字节。
关于c - 在套接字上写入和读取返回不同的字节数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37378296/