socket发送函数。
int send( SOCKET s, const char FAR *buf, int len, int flags );
如果内容是动态生成的,一般是把传输内容直接丢给buf中用send函数传输,没有优化的空间。
文件传输则要先把内容read到buf中,因此至少两次内核调用,如果文件很大,可能会用一个循环调用,如:
while( size == PER_SIZE ) { size = read( fd, buf, PER_SIZE ); if( size >0 ) { send( sock, buf, size, 0 ); } }
系统调用的个数将会是 文件大小/每次读取大小*2,我们知道系统调用需要内核态与用户态的切换,还有系统内存与用户内在的拷贝,比较浪费宝贵的CPU时间。
静态文件的传输大量的存在,如html,css,js,传输效率是服务器绕不开的问题,的确需要专门的优化。
linux 自2.1后开始用 sendfile 来专门解决这类问题。
我们来看看函数声明:
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
参数已经很明显,就不再介绍。
这个函数只需要用户态与内核态切换一次,所有的操作都在内核操作,节约了大量的CPU时间,也没有用户内存与内核内存的切换,即实现了“0拷贝”。
函数内部其实是在 in_fd,outfd之前建了管道传输,不再介绍。
这个技术在现在的web server中得到大量使用,可以说静态文件的快速传输就靠它了。