测试能用的sendfile例程

send.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <ctype.h>
#include <sys/epoll.h>
#include <mysql/mysql.h>
#include <pthread.h>
#include <libgen.h>
#include <sys/sendfile.h>
#include <fcntl.h>
#include "time.h"

#define BUFSIZE 1024

void my_err(const char *str, const int line)
{
    fprintf(stderr, "%d : %s : %s", line, str, strerror(errno));
    exit(1);
}

int Read(int fd, char *buf, size_t count, int line)
{
    int n = 0;
    memset(buf, 0, count);

    n = read(fd, buf, count);
    // printf("readn = %d\n", n);
    // printf("readbuf = %s\n", buf);
    if(n < 0)
    {
        my_err("read error", line);
    }
    return n;
}

void Write(int fd, const char *buf)
{  
    int n;
    if((n = write(fd, buf, BUFSIZ)) == -1)
    {   
        my_err("write error", __LINE__);
    }
}

int main(int argc, char **argv)
{
    //检查参数个数
    if(argc != 5)
    {
        printf("Usage: [-p] [serv_port] [-a] [serve_address]\n");
        exit(1);
    }
    int i;
    int serv_port;
    struct sockaddr_in serv_addr;

    serv_addr.sin_family = AF_INET;
    // serv_addr.sin_port = htons(SERV_PORT);
    // inet_aton("127.0.0.1", &serv_addr.sin_addr);
    //从命令行的输入获取服务器端的端口与地址
    for(i=1; i<argc; i++)
    {
        if(strcmp(argv[i], "-p") == 0)
        {
            serv_port = atoi(argv[i+1]);
            if(serv_port < 0 || serv_port > 65535)
            {
                printf("Invalid serv_addr.sin_port\n");
                exit(1);
            }
            else
            {
                serv_addr.sin_port = htons(serv_port);
            }
            continue;
        }

        if(strcmp(argv[i], "-a") == 0)
        {
            if(inet_aton(argv[i+1], &serv_addr.sin_addr) == 0)
            {
                printf("Invalid server ip address\n");
                exit(1);
            }
            continue;
        }
    }

    int cfd;
    char buf[BUFSIZE];
    int len;

    cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(cfd == -1)
        my_err("socket error", __LINE__);

    if(connect(cfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
        my_err("connect error", __LINE__);

    char file_path[BUFSIZE];
    char *file_name;
    char temp[BUFSIZE];
    struct stat buffer;

    printf("输入完整的文件名:");
    scanf("%s", file_path);
    //判断输入是否正确
    //如果目标文件或目录不存在就会报错
    if(stat(file_path, &buffer) == -1)
    {
        printf("---非法的路径名---\n");
        return 0;
    }
    file_name = basename(file_path);
    struct node
    {
        int len;
        char name[100];
    }node;
    node.len = buffer.st_size;
    strcpy(node.name, file_name);
    
    memcpy(temp, &node, sizeof(node));
    write(cfd, temp, sizeof(temp));
    
    //开始向服务器的文件缓冲区发送文件
    int fp = open(file_path, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR);

    printf("---开始传送文件:%s---\n", node.name);
    sendfile(cfd, fp, 0, buffer.st_size);
    printf("---文件<%s>传送成功---\n", node.name);

    close(fp);
    // close(cfd);

    return 0;
}

recv.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <ctype.h>
#include <sys/epoll.h>
#include <mysql/mysql.h>
#include <pthread.h>
#include <libgen.h>
#include <sys/sendfile.h>
#include <fcntl.h>
#include "time.h"

#define SERV_PORT 4507
#define BUFSIZE 1024
void my_err(const char *str, const int line)
{
    fprintf(stderr, "%d : %s : %s", line, str, strerror(errno));
    exit(1);
}

int Read(int fd, char *buf, size_t count, int line)
{
    int n = 0;
    memset(buf, 0, count);

    n = read(fd, buf, count);
    if(n < 0)
    {
        my_err("read error", line);
    }
    return n;
}

void Write(int fd, const char *buf)
{  
    int n;
    if((n = write(fd, buf, BUFSIZE)) == -1)
    {   
        my_err("write error", __LINE__);
    }
}

int main()
{
    int lfd, cfd;
    int clit_addr_len;
    struct sockaddr_in serv_addr, clit_addr;
    
    //初始化服务器
    lfd = socket(AF_INET, SOCK_STREAM, 0);
    if(lfd == -1)
        my_err("socket error", __LINE__);

    int optval = 1;
    if(setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (void *)&optval, sizeof(int)) < 0)
        my_err("setsockopt error", __LINE__);

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if(bind(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
        my_err("bind error", __LINE__);

    if(listen(lfd, 128) == -1)
        my_err("listen error", __LINE__);

    clit_addr_len = sizeof(clit_addr);
    cfd = accept(lfd, (struct sockaddr *)&clit_addr, &clit_addr_len);
    if(cfd == -1)
        my_err("accept error", __LINE__);

    char buf[BUFSIZ];
    char temp[BUFSIZE];
    char name[100];

    struct node
    {
        int len;
        char name[100];
    }node;

    memset(temp, 0, sizeof(temp));
    read(cfd, temp, sizeof(temp));
    memcpy(&node, temp, sizeof(node));

    sprintf(temp, "./file_recv/%s", node.name);
    //创建文件
    FILE *fp = fopen(temp, "wb");
    if (fp == NULL) 
    {
        perror("Can't open file");
        exit(1);
    }
    
    //把数据写入文件
    printf("Start receive file: %s from %s\n", temp, inet_ntoa(clit_addr.sin_addr));

    int n;
    int sum = 0;
    while((n = Read(cfd, buf, BUFSIZ, __LINE__)) > 0)
    {   
        // printf("n = %d\n", n);
        fwrite(buf, sizeof(char), n, fp);
        sum += n;
        if(sum >= node.len)
        {
            break;
        }
    }

    // Read(cfd, buf, node.len, __LINE__);
    // fwrite(buf, sizeof(char), node.len, fp);
    
    
    puts("Receive Success");

    // 关闭文件
    fclose(fp);    



    close(lfd);
    close(cfd);

    return 0;
}

Makefile:

.PHONY:all

all:send recv

send:send.o
	gcc -o send send.o

recv:recv.o
	gcc -o recv recv.o

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值