我正在处理的服务器(这是一个Unix C多线程非块套接字服务器)需要从客户端接收文件并将其广播到连接到服务器的所有其他客户端。
除了我很难确定文件何时完成传输时,一切都正常工作...因为我使用非块套接字我有问题,有时在文件传输recv返回-1(我,假设是文件的结尾)然后下一个传递更多的字节进来。
我试图破解整个事情,将“END”放在流的末尾。但是,有时当连续发送多个文件时,“END”是与下一个文件开头相同的recv缓冲区的一部分。或者甚至最糟糕的是,有时我最终会得到一个以EN结束的缓冲区,然后是D的下一个传递。
避免上述情况的最佳方法是什么,我真的不希望每次从套接字循环中收到一些字节时,整个累积缓冲区检查“END”是否是其中的一部分然后适当切割......我确定有更好的解决方案吗?
提前致谢!
答案 0 :(得分:2)
如果recv()
返回-1,则为错误,您需要检查errno
。最有可能是EAGAIN
或EWOULDBLOCK
,这意味着套接字接收缓冲区中当前没有数据。所以你需要重新选择()。
当recv()
返回零时,对等方已断开套接字并且传输已完成。
答案 1 :(得分:1)
使用某个字节序列发送文件末尾的信号不可靠,文件可能包含该序列。首先发送文件长度 - 如果允许大量文件传输,则为4个字节或8个,使用网络字节顺序。
if ((n = read(..., filelen)) > 0) {
filelen -= n;
}
答案 2 :(得分:0)
EJP所指的最简单的情况是,你将套接字的另一端关闭作为文件结尾,可能如下所示:
{
ssize_t sizeRead = 0;
while (sizeRead = recv(...)) {
if (0 > sizeRead) { /* recv() failed */
if ((EGAGAIN == errno) ¦¦ (EWOULDBLOCK == errno)) { /* retry the recv() on those two kinds of error */
usleep(1) /* optional */
continue;
}
else
break;
}
... /* process the data read ... */
}
if (0 > sizeRead) {
/* There had been an error during recv() */
}
}