gpt4 book ai didi

C:AF_UNIX 套接字上的剩余字节

转载 作者:行者123 更新时间:2023-11-30 18:10:51 26 4
gpt4 key购买 nike

我在 AF_UNIX 套接字通信方面遇到了一些问题,因为在写入数据缓冲区后,似乎仍然有一些挂起的字节需要读取,但我不知道它们来自哪里。

我正在用 C 编写一个多线程服务器程序,通过 AF_UNIX 套接字与客户端通信,它必须实现一个简单的聊天室。除此之外,服务器必须实现客户端和服务器之间的文件传输,当我尝试从服务器向客户端发送相当大的文件(269K)时遇到问题。 (对于较小的文件,我没有任何问题)

对于文件传输,我使用 mmap() 函数,该函数返回指向我要发送的文件的映射的指针,然后我使用 write() 进行写入与必须接收文件的客户端链接的套接字上的数据。在 write() 调用之后,我检查返回的值是否等于文件大小。 (始终经过验证)

客户端收到文件后,检查读取数据的大小(始终验证)并开始等待其他消息,因此它调用阻塞的read()是我发现错误的地方,因为客户端读取了不应该存在的内容,就好像套接字上还有一些内容需要读取。我已经调试这部分(服务器和客户端)两天了,但我还无法理解问题的根源。

我确信没有其他线程同时在同一个套接字上写入

你们中有人知道这个错误的原因是什么吗?

我尝试在正常操作顺序下发布一些有用的代码思考:

首先是消息结构:

struct message_hdr
{
op_t op;
char sender[MAX_NAME_LENGTH+1];
};

struct message_data_hdr{
char receiver[MAX_NAME_LENGTH+1];
unsigned int len;
};

struct message_data
{
message_data_hdr_t hdr;
char *buf;
};

struct message
{
message_hdr_t hdr;
message_data_t data;
};

服务器->客户端文件传输从服务器发送 message_hdr_t 到等待 read() 的客户端开始(客户端期望仅接收message_hdr_t)。

int sendHeader(long fd, message_hdr_t* hdr)
{
if(hdr == NULL || fd < 0) {errno = EINVAL; return -1;}

int test;
struct iovec iov;

iov.iov_base = hdr;
iov.iov_len = sizeof(message_hdr_t);

test = writev(fd, &iov, 1);

return test;
}

客户端从操作代码(message.hdr.op)中了解到这是一条文件类型消息,并开始等待文件,

所以服务器发送它:

int sendData(long fd, message_data_t *msg)
{
if(msg == NULL || fd < 0) {errno = EINVAL; return -1;}

int test;
struct iovec iov;

iov.iov_base = &(msg->hdr);
iov.iov_len = sizeof(message_data_hdr_t);

test = writev(fd, &(iov), 1);
if(test == -1){return -1;}

if (msg->hdr.len != 0)
{
test = write(fd, msg->buf, msg->hdr.len);
if(test <= 0)
return -1;
}

return test;
}

客户阅读它:

int readData(long fd, message_data_t *data)
{
if(data == NULL || fd < 0) {errno = EINVAL; return -1;}

int test;
struct iovec iov;

iov.iov_base = &(data->hdr);
iov.iov_len = sizeof(message_data_hdr_t);

test = readv(fd, &iov, 1);
if(test <= 0){return -1;}

if(data->hdr.len != 0)
{
data->buf = malloc(data->hdr.len);
if(data->buf == NULL){return -1;}

test = read(fd, data->buf, data->hdr.len);
if((unsigned int)test != data->hdr.len)
return -1;
}

return test;
}

此时客户端收到文件,并重新开始等待新消息:

int readMsg(long fd, message_t *msg)
{
if(msg == NULL || fd < 0) {errno = EINVAL; return -1;}

int test;

test = readHeader(fd, &(msg->hdr));
if(test == -1 || test == 0){return -1;}

test += readData(fd, &(msg->data));
return test;
}

这是客户端应该简单等待的点,因为没有收入消息,在这种情况下它读取了一些我不知道它来自哪里的东西。

当我尝试使用 GDB 打印这条不需要的消息时,它会打印:

{hdr = {op = 512, 
sender = "\000\000\020G\032\324\t\000\000\n\000\000\000\000\030\021B\bC\n\000\000\v\000\000\000\000\021D\v\222\000"},
data = {hdr = {receiver = "\000\000\000\000\021E\022C\n\000\000\b\v\000\000\000\000\021F\020I\n\000\000\020\000\006\b\002\n\000\000\006",
len = 131072},
buf = 0x7ffff7f2f010 ""}`

当然这是没有意义的。

我希望这个描述有用

提前谢谢大家。

最佳答案

好的,我解决了我的问题。正如评论中所写,这个问题是由于缺乏对部分写入的检查

现在函数 readData() 看起来像这样:

int readData(long fd, message_data_t *data)
{
if(data == NULL || fd < 0) {errno = EINVAL; return -1;}

int test;
char* ph;
unsigned int rd = 0;
struct iovec iov;

iov.iov_base = &(data->hdr);
iov.iov_len = sizeof(message_data_hdr_t);

test = readv(fd, &iov, 1);
if(test <= 0){return -1;}

if(data->hdr.len != 0)
{
data->buf = malloc(data->hdr.len);
if(data->buf == NULL){return -1;}

ph = data->buf;

while (rd < data->hdr.len)
{
test = read(fd, ph, data->hdr.len - rd);
if(test == -1)
return -1;
else if(test == 0)
{
errno = ENOENT;
return -1;
}

rd += test;
ph += test;
}
}

return rd;
}

sendData():

int sendData(long fd, message_data_t *msg)
{
if(msg == NULL || fd < 0) {errno = EINVAL; return -1;}

int test;
char* ph;
unsigned int wr = 0;
struct iovec iov;

iov.iov_base = &(msg->hdr);
iov.iov_len = sizeof(message_data_hdr_t);

test = writev(fd, &(iov), 1);
if(test == -1){return -1;}

if(msg->hdr.len != 0)
{
ph = msg->buf;

while (wr < msg->hdr.len)
{
test = write(fd, ph, msg->hdr.len - wr);
if(test == -1)
return -1;
else if(test == 0)
{
errno = ENOENT;
return -1;
}

wr += test;
ph += test;
}
}

return test;
}

这样我就不再发现错误了。

感谢您的帮助!

关于C:AF_UNIX 套接字上的剩余字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54552515/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com