sendfile函数

sendfile函数:

函数原型:

      #include <sys/sendfile.h>

       ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);


sendfile在两个文件描述符之间直接传输数据(完全在内核中操作),从而避免了内核缓冲区和用户缓冲区之间拷贝数据,效率很高,这被称为零拷贝.

out_fd: 待写入数据的文件描述符

in_fd:待读出数据的文件描述符

offset:指定从读入文件流的哪个位置开始读书据,如果为空,则采用默认的读入文件其起始位置

count:指定在in_fd 和out_fd 之间传输的数据字节数

函数返回值:成功传输的字节数

注意:

in_fd 必须是真实存在的文件,不能是socket和管道

out_fd 必须是一个socket.

测试代码:

#define _GNU_SOURCE         /* See feature_test_macros(7) */
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<stdio.h>
#include<errno.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
#include<stdlib.h>
#include<sys/epoll.h>
#include<pthread.h>

#include<libgen.h>

ser.c文件:

#include"../utili.h"

int main(int argc,char *argv[])
{
    if(argc<=3)
    {
        printf("usage: %s  ip  port_number\n",basename(argv[0]));
        return 1;
    }
    const char*ip = argv[1];
    int port = atoi(argv[2]);
    const char *file_name = argv[3];

    int filefd = open(file_name,O_RDONLY);
    assert(filefd>0);
    struct stat stat_buf;
    fstat(filefd,&stat_buf);

    struct sockaddr_in address;
    bzero(&address,sizeof(address));
    address.sin_family = AF_INET;
    address.sin_port = htons(port);
    inet_pton(AF_INET,ip,&address.sin_addr);

    int sock = socket(AF_INET,SOCK_STREAM,0);
    assert(sock>=0);
    socklen_t len = sizeof(address);
    int ret = bind(sock,(struct sockaddr*)&address,len);
    assert(ret!=-1);

    ret = listen(sock,5);
    assert(ret!=-1);

    struct sockaddr_in client;
    socklen_t client_len = sizeof(client);
    int connfd = accept(sock,(struct sockaddr*)&client,&client_len);
    if(connfd<0)
    {
        printf("errno: %d\n",errno);
    }
    else
    {
        sendfile(connfd,filefd,NULL,stat_buf.st_size);
        close(connfd);
    }
close(sock);
return 0;
}
cli.c文件:

#include"../utili.h"

int main(int argc,char *argv[])
{
    const char *ip = argv[1];
    int port = atoi(argv[2]);

    struct sockaddr_in addrSer;
    bzero(&addrSer,sizeof(addrSer));
    addrSer.sin_family = AF_INET;
    addrSer.sin_port = htons(port);
    inet_pton(AF_INET,ip ,&addrSer.sin_addr);

    int sock = socket(AF_INET,SOCK_STREAM,0);
    assert(sock>=0);
    
    int ret = connect(sock,(struct sockaddr*)&addrSer,sizeof(addrSer));
    assert(ret>=0);

    char buf[50];

    while(1)
    {
        ret = recv(sock,buf,50,0);
        if(ret<0)
        break;
        else if(ret == 0)
        {
            printf("sever close connextion\n");
            break;
        }
        else
        printf("get %d bytes :  %s\n",(int)strlen(buf),buf);
    }
    close(sock);
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值