我想使用sockets和能够发送和接收文件的C/C++语言在Linux上实现一个客户机-服务器体系 struct .有没有图书馆能让这项任务变得简单?谁能举个例子吗?
我想使用sockets和能够发送和接收文件的C/C++语言在Linux上实现一个客户机-服务器体系 struct .有没有图书馆能让这项任务变得简单?谁能举个例子吗?
最具可移植性的解决方案就是将文件分块读取,然后以循环的方式将数据写入套接字(同样,在接收文件时也是如此).您分配一个缓冲区,read
到该缓冲区,write
从该缓冲区到您的套接字(您也可以使用send
和recv
,这是特定于套接字的数据写入和读取方式).大纲应该是这样的:
while (1) {
// Read data into buffer. We may not have enough to fill up buffer, so we
// store how many bytes were actually read in bytes_read.
int bytes_read = read(input_file, buffer, sizeof(buffer));
if (bytes_read == 0) // We're done reading from the file
break;
if (bytes_read < 0) {
// handle errors
}
// You need a loop for the write, because not all of the data may be written
// in one call; write will return how many bytes were written. p keeps
// track of where in the buffer we are, while we decrement bytes_read
// to keep track of how many bytes are left to write.
void *p = buffer;
while (bytes_read > 0) {
int bytes_written = write(output_socket, p, bytes_read);
if (bytes_written <= 0) {
// handle errors
}
bytes_read -= bytes_written;
p += bytes_written;
}
}
确保仔细阅读read
和write
的文档,尤其是在处理错误时.一些错误代码意味着你应该再试一次,例如用continue
语句再次循环,而另一些则意味着有些东西坏了,你需要停止.
要将文件发送到套接字,有一个系统调用sendfile
,它只执行您想要的操作.它告诉内核将一个文件从一个文件描述符发送到另一个文件描述符,然后内核可以处理其余的文件.需要注意的是,源文件描述符必须支持mmap
(如中所示,是实际文件,而不是套接字),目标必须是套接字(因此不能使用它复制文件,或直接从一个套接字向另一个套接字发送数据);它旨在支持您描述的将文件发送到套接字的用法.然而,这无助于接收文件;你需要自己做这个循环.我不能告诉你为什么有sendfile
个电话,但没有类似的recvfile
个.
注意sendfile
是特定于Linux的;它不能移植到其他系统.其他系统通常有自己的sendfile
版本,但具体的接口可能会有所不同(FreeBSDMac OS XSolaris).
在Linux 2.6.17中,splice
系统调用是introduced,而在2.6.23中是used internally to implement sendfile
.splice
是比sendfile
更通用的API.有关splice
和tee
的详细描述,请参见相当好的explanation from Linus himself.他指出,使用splice
基本上就像上面的循环一样,使用read
和write
,只是缓冲区在内核中,所以数据不必在内核和用户空间之间传输,甚至可能永远不会通过CPU(称为"零拷贝I/O").