Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Linux上sendfileapi的测量_C_Linux_Network Programming - Fatal编程技术网

C Linux上sendfileapi的测量

C Linux上sendfileapi的测量,c,linux,network-programming,C,Linux,Network Programming,我编写了一个简单的文件复制应用程序来衡量使用sendfileapi对大文件的有效性,而不是常规的从文件读取和向套接字写入方法。然而,在使用这两种方法运行应用程序时,我发现两种方法之间完成文件拷贝所需的时间差异非常小 我从多个来源了解到,“sendfile”API将比普通的从文件读取和向套接字写入的方法提供巨大的性能改进。但当我尝试使用单个2GB文件进行基准测试时,以下是我观察到的数字(平均4次迭代): 正常的文件读写套接字方法:17秒444840 usecs sendfileapi:17秒431

我编写了一个简单的文件复制应用程序来衡量使用sendfileapi对大文件的有效性,而不是常规的从文件读取和向套接字写入方法。然而,在使用这两种方法运行应用程序时,我发现两种方法之间完成文件拷贝所需的时间差异非常小

我从多个来源了解到,“sendfile”API将比普通的从文件读取和向套接字写入的方法提供巨大的性能改进。但当我尝试使用单个2GB文件进行基准测试时,以下是我观察到的数字(平均4次迭代):

  • 正常的文件读写套接字方法:17秒444840 usecs
  • sendfileapi:17秒431420 usecs
  • 我在一个隔离的1Gbps网络中的两台不同机器(Linux内核版本4.4.162-94.72-default)上运行应用程序的服务器和客户端

    有人能帮我一下我到底做错了什么或错过了什么

    服务器:

    #define _GNU_SOURCE
    
    #include "file_details.h"
    
    void calculate_execution_time(struct timeval start, struct timeval end)
    {
        struct timeval  time_diff;
    
    
        time_diff.tv_sec = end.tv_sec - start.tv_sec;
        time_diff.tv_usec = end.tv_usec - start.tv_usec;
    
        // Adjust the time appropriately
        while (time_diff.tv_usec < 0) {
            time_diff.tv_sec--;
            time_diff.tv_usec += 1000000;
        }
    
        printf("total execution time: = %lds.%ldus\n", time_diff.tv_sec, time_diff.tv_usec);
    }
    
    
    int read_from_file_pread(int client_sockfd, char *file_name, int fd, off_t file_size_in_bytes, int chunk_size)
    {
        ssize_t         bytes_read = 0, bytes_sent = 0, total_bytes_sent = 0, bytes_sent_this_itr = 0;
        off_t           offset = 0;
        char            *buffer = NULL;
        struct timeval      start_time, end_time;
    
    
        buffer = calloc(chunk_size, sizeof(char));
        if (buffer == NULL) {
            printf("Failed to allocate memory of size: %d bytes\n", chunk_size);
            return -1;
        }
    
        gettimeofday(&start_time, NULL);
    
        do {
            bytes_read = pread(fd, buffer, chunk_size, offset);
            switch (bytes_read) {
                case -1:
                    printf("Failed to read from file: %s, offset: %lu, error: %d\n", file_name, offset, errno);
    
                    free(buffer);
                    return -1;
    
                case 0:
                    printf("Completed reading from file and sending\n");
                    break;
    
                default:
                    do {
                        bytes_sent = send(client_sockfd, buffer, (bytes_read - bytes_sent_this_itr), 0);
                        if (bytes_sent == -1) {
                            printf("Failed to send %lu bytes, error: %d\n", (bytes_read - bytes_sent_this_itr), errno);
    
                            free(buffer);
                            return -1;
                        }
    
                        bytes_sent_this_itr += bytes_sent;
                    } while (bytes_sent_this_itr < bytes_read);
    
                    bytes_sent = 0;
                    bytes_sent_this_itr = 0;
                    offset += bytes_read;
                    total_bytes_sent += bytes_read;
                    break;
            }
        } while (total_bytes_sent < file_size_in_bytes);
    
        gettimeofday(&end_time, NULL);
    
        printf("File size: %lu bytes, total bytes read from file: %lu, ", file_size_in_bytes, total_bytes_sent);
    
        calculate_execution_time(start_time, end_time);
    
        free(buffer);
        return 0;
    }
    
    
    int read_from_file_sendfile(int client_sockfd, char *file_name, int fd, off_t file_size_in_bytes, int chunk_size)
    {
        ssize_t         bytes_sent = 0, total_bytes_sent = 0;
        off_t           offset = 0;
        struct timeval      start_time, end_time;
    
    
        gettimeofday(&start_time, NULL);
    
        do {
            bytes_sent = sendfile(client_sockfd, fd, &offset, chunk_size);
            if (bytes_sent == -1) {
                printf("Failed to sendfile: %s, offset: %lu, error: %d\n", file_name, offset, errno);
                return -1;
            }
    
            total_bytes_sent += bytes_sent;
        } while (total_bytes_sent < file_size_in_bytes);
    
        gettimeofday(&end_time, NULL);
    
        printf("File size: %lu bytes, total bytes read from file: %lu, ", file_size_in_bytes, total_bytes_sent);
    
        calculate_execution_time(start_time, end_time);
    
        return 0;
    }
    
    
    int read_from_file(int client_sockfd, char *file_name, char *type, int chunk_size)
    {
        int         error_code = 0, fd = 0;
        ssize_t         hdr_length = 0, bytes_sent = 0, file_name_length = strlen(file_name);
        struct stat     file_stat = {0};
        struct file_details *file_details_to_send = NULL;
    
    
        fd = open(file_name, O_RDONLY, S_IRUSR);
        if (fd == -1) {
                    printf("Failed to open file: %s, error: %d\n", file_name, errno);
                    return -1;
        }
    
        error_code = fstat(fd, &file_stat);
        if (error_code == -1) {
                    printf("Failed to get status of file: %s, error: %d\n", file_name, errno);
    
            close(fd);
            return -1;
        }
    
        hdr_length = (sizeof(struct file_details) + file_name_length + 1);
        file_details_to_send = calloc(hdr_length, sizeof(char));
        if (file_details_to_send == NULL) {
            perror("Failed to allocate memory");
    
            close(fd);
            return -1;
        }
    
        file_details_to_send->file_name_length = file_name_length;
        file_details_to_send->file_size_in_bytes = file_stat.st_size;
        strcpy(file_details_to_send->file_name, file_name);
    
        printf("File name: %s, size: %lu bytes\n", file_name, file_stat.st_size);
    
        bytes_sent = send(client_sockfd, file_details_to_send, hdr_length, 0);
        if (bytes_sent == -1) {
            printf("Failed to send header of size: %lu bytes, error: %d\n", hdr_length, errno);
    
            close(fd);
            return -1;
        }
    
        if (strcmp(type, "rw") == 0) {
            printf("By pread and send\n");
    
            read_from_file_pread(client_sockfd, file_name, fd, file_stat.st_size, chunk_size);
        } else {
            printf("By sendfile\n");
    
            read_from_file_sendfile(client_sockfd, file_name, fd, file_stat.st_size, chunk_size);
        }
    
        close(fd);
        return 0;
    }
    
    
    int main(int argc, char *argv[])
    {
        ...
        ...
    
        option_value = 1;
        error_code = setsockopt(client_sockfd, SOL_TCP, TCP_NODELAY, &option_value, sizeof(int));
        if (error_code == -1) {
            printf("Failed to set socket option TCP_NODELAY to socket descriptor: %d, error: %d", client_sockfd, errno);
        }
    
        read_from_file(client_sockfd, file_name, type, chunk_size);
    
        ...
    }
    
    定义GNU源
    #包括“文件\u details.h”
    无效计算执行时间(结构时间值开始,结构时间值结束)
    {
    结构时间差;
    time_diff.tv_sec=end.tv_sec-start.tv_sec;
    time_diff.tv_usec=end.tv_usec-start.tv_usec;
    //适当调整时间
    同时(时间差电视节目<0){
    时差电视秒;
    时间差电视使用次数+=1000000;
    }
    printf(“总执行时间:=%lds.%ldus\n”,时间差电视秒,时间差电视秒);
    }
    int从文件读取(int客户端sockfd,字符*文件名,int fd,关闭文件大小(以字节为单位),int块大小)
    {
    ssize_t bytes_read=0,bytes_sent=0,total_bytes_sent=0,bytes_sent_this_itr=0;
    off_t offset=0;
    char*buffer=NULL;
    结构时间值开始时间、结束时间;
    buffer=calloc(chunk_size,sizeof(char));
    if(buffer==NULL){
    printf(“分配大小为%d字节的内存失败”,chunk\u size);
    返回-1;
    }
    gettimeofday(&开始时间,NULL);
    做{
    字节读取=前置(fd、缓冲区、块大小、偏移量);
    开关(字节\读取){
    案例1:
    printf(“读取文件%s失败,偏移量:%lu,错误:%d\n”,文件名,偏移量,错误号);
    自由(缓冲);
    返回-1;
    案例0:
    printf(“从文件读取并发送完成”);
    打破
    违约:
    做{
    字节发送=发送(客户端sockfd,缓冲区,(字节读取-字节发送,此itr),0);
    如果(发送的字节数==-1){
    printf(“发送%lu字节失败,错误:%d\n”,(字节\u读取-字节\u发送\u此itr),错误号);
    自由(缓冲);
    返回-1;
    }
    已发送字节数\u此\u itr+=已发送字节数;
    }while(已发送的字节数<读取的字节数);
    发送的字节数=0;
    发送的字节数=0;
    偏移量+=读取的字节数;
    发送的总字节数+=读取的字节数;
    打破
    }
    }while(发送的总字节数<文件大小,以字节为单位);
    gettimeofday(&end_time,NULL);
    printf(“文件大小:%lu字节,从文件读取的总字节数:%lu,”,文件大小(单位:字节),发送的总字节数);
    计算执行时间(开始时间、结束时间);
    自由(缓冲);
    返回0;
    }
    int read_from_file_sendfile(int client_sockfd,char*file_name,int fd,off_t file_size_字节,int chunk_size)
    {
    ssize_t bytes_sent=0,total_bytes_sent=0;
    off_t offset=0;
    结构时间值开始时间、结束时间;
    gettimeofday(&开始时间,NULL);
    做{
    字节\u发送=发送文件(客户端\u sockfd、fd和偏移量、块大小);
    如果(发送的字节数==-1){
    printf(“发送文件失败:%s,偏移量:%lu,错误:%d\n”,文件名,偏移量,错误号);
    返回-1;
    }
    发送的总字节数+=发送的字节数;
    }while(发送的总字节数<文件大小,以字节为单位);
    gettimeofday(&end_time,NULL);
    printf(“文件大小:%lu字节,从文件读取的总字节数:%lu,”,文件大小(单位:字节),发送的总字节数);
    计算执行时间(开始时间、结束时间);
    返回0;
    }
    从文件读取的整型数据(整型客户端数据,字符*文件名,字符*类型,整型数据块大小)
    {
    int error_code=0,fd=0;
    ssize_t hdr_length=0,bytes_sent=0,file_name_length=strlen(file_name);
    struct stat file_stat={0};
    struct file_details*file_details_to_send=NULL;
    fd=打开(文件名,仅限O rdu,S IRUSR);
    如果(fd==-1){
    printf(“无法打开文件:%s,错误:%d\n”,文件名,错误号);
    返回-1;
    }
    错误代码=fstat(fd和文件统计);
    如果(错误代码==-1){
    printf(“无法获取文件%s的状态,错误:%d\n”,文件名,错误号);
    关闭(fd);
    返回-1;
    }
    hdr_长度=(sizeof(结构文件_详细信息)+文件名_长度+1);
    file_details_to_send=calloc(hdr_长度,sizeof(char));
    if(文件详细信息到发送==NULL){
    perror(“分配内存失败”);
    关闭(fd);
    返回-1;
    }
    文件\详细信息\发送->文件\名称\长度=文件\名称\长度;
    文件详细信息发送->文件大小(以字节为单位)=file\u stat.st\u size;
    strcpy(文件详细信息发送->文件名,文件名);
    printf(“文件名:%s,大小:%lu字节\n”,文件名,文件统计.st\u大小);
    字节发送=发送(客户端sockfd,文件详细信息发送,hdr长度,0);
    如果(发送的字节数==-1){
    printf(“未能发送大小为:%lu字节的标头,错误:%d\n”,hdr\u长度,错误号);
    关闭(fd);
    返回-1;
    }
    if(strcmp(类型,“rw”)==0){
    printf(“通过pread和send\n”);
    从文件序言中读取(客户端、文件名、文件名、文件大小、块大小);
    }否则{
    printf(“通过sendfile\n”);