⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sendfile.c

📁 apache的软件linux版本
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <assert.h>#include <errno.h>#include <signal.h>#include <stdlib.h>#include <string.h>#include "apr_network_io.h"#include "apr_errno.h"#include "apr_general.h"#include "apr_poll.h"#if !APR_HAS_SENDFILEint main(void){    fprintf(stderr,             "This program won't work on this platform because there is no "            "support for sendfile().\n");    return 0;}#else /* !APR_HAS_SENDFILE */#define FILE_LENGTH    200000#define FILE_DATA_CHAR '0'#define HDR1           "1234567890ABCD\n"#define HDR2           "EFGH\n"#define HDR3_LEN       80000#define HDR3_CHAR      '^'#define TRL1           "IJKLMNOPQRSTUVWXYZ\n"#define TRL2           "!@#$%&*()\n"#define TRL3_LEN       90000#define TRL3_CHAR      '@'#define TESTSF_PORT    8021#define TESTFILE       "testsf.dat"typedef enum {BLK, NONBLK, TIMEOUT} client_socket_mode_t;static void apr_setup(apr_pool_t **p, apr_socket_t **sock, int *family){    char buf[120];    apr_status_t rv;    rv = apr_initialize();    if (rv != APR_SUCCESS) {        fprintf(stderr, "apr_initialize()->%d/%s\n",                rv,                apr_strerror(rv, buf, sizeof buf));        exit(1);    }    atexit(apr_terminate);    rv = apr_pool_create(p, NULL);    if (rv != APR_SUCCESS) {        fprintf(stderr, "apr_pool_create()->%d/%s\n",                rv,                apr_strerror(rv, buf, sizeof buf));        exit(1);    }    *sock = NULL;    rv = apr_socket_create(sock, *family, SOCK_STREAM, *p);    if (rv != APR_SUCCESS) {        fprintf(stderr, "apr_socket_create()->%d/%s\n",                rv,                apr_strerror(rv, buf, sizeof buf));        exit(1);    }    if (*family == APR_UNSPEC) {        apr_sockaddr_t *localsa;        rv = apr_socket_addr_get(&localsa, APR_LOCAL, *sock);        if (rv != APR_SUCCESS) {            fprintf(stderr, "apr_socket_addr_get()->%d/%s\n",                    rv,                    apr_strerror(rv, buf, sizeof buf));            exit(1);        }        *family = localsa->family;    }}static void create_testfile(apr_pool_t *p, const char *fname){    apr_file_t *f = NULL;    apr_status_t rv;    char buf[120];    int i;    apr_finfo_t finfo;    printf("Creating a test file...\n");    rv = apr_file_open(&f, fname,                  APR_CREATE | APR_WRITE | APR_TRUNCATE | APR_BUFFERED,                 APR_UREAD | APR_UWRITE, p);    if (rv) {        fprintf(stderr, "apr_file_open()->%d/%s\n",                rv, apr_strerror(rv, buf, sizeof buf));        exit(1);    }        buf[0] = FILE_DATA_CHAR;    buf[1] = '\0';    for (i = 0; i < FILE_LENGTH; i++) {        /* exercise apr_file_putc() and apr_file_puts() on buffered files */        if ((i % 2) == 0) {            rv = apr_file_putc(buf[0], f);            if (rv) {                fprintf(stderr, "apr_file_putc()->%d/%s\n",                        rv, apr_strerror(rv, buf, sizeof buf));                exit(1);            }        }        else {            rv = apr_file_puts(buf, f);            if (rv) {                fprintf(stderr, "apr_file_puts()->%d/%s\n",                        rv, apr_strerror(rv, buf, sizeof buf));                exit(1);            }        }    }    rv = apr_file_close(f);    if (rv) {        fprintf(stderr, "apr_file_close()->%d/%s\n",                rv, apr_strerror(rv, buf, sizeof buf));        exit(1);    }    rv = apr_stat(&finfo, fname, APR_FINFO_NORM, p);    if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) {        fprintf(stderr, "apr_stat()->%d/%s\n",                rv, apr_strerror(rv, buf, sizeof buf));        exit(1);    }    if (finfo.size != FILE_LENGTH) {        fprintf(stderr,                 "test file %s should be %ld-bytes long\n"                "instead it is %ld-bytes long\n",                fname,                (long int)FILE_LENGTH,                (long int)finfo.size);        exit(1);    }}static int client(client_socket_mode_t socket_mode, char *host){    apr_status_t rv, tmprv;    apr_socket_t *sock;    apr_pool_t *p;    char buf[120];    apr_file_t *f = NULL;    apr_size_t len;    apr_size_t expected_len;    apr_off_t current_file_offset;    apr_hdtr_t hdtr;    struct iovec headers[3];    struct iovec trailers[3];    apr_size_t bytes_read;    apr_pollfd_t *pfd;    apr_int32_t nsocks;    int i;    int family;    apr_sockaddr_t *destsa;    family = APR_INET;    apr_setup(&p, &sock, &family);    create_testfile(p, TESTFILE);    rv = apr_file_open(&f, TESTFILE, APR_READ, 0, p);    if (rv != APR_SUCCESS) {        fprintf(stderr, "apr_file_open()->%d/%s\n",                rv,                apr_strerror(rv, buf, sizeof buf));        exit(1);    }    if (!host) {        host = "127.0.0.1";    }    rv = apr_sockaddr_info_get(&destsa, host, family, TESTSF_PORT, 0, p);    if (rv != APR_SUCCESS) {        fprintf(stderr, "apr_sockaddr_info_get()->%d/%s\n",                rv,                apr_strerror(rv, buf, sizeof buf));        exit(1);    }    rv = apr_socket_connect(sock, destsa);    if (rv != APR_SUCCESS) {        fprintf(stderr, "apr_socket_connect()->%d/%s\n",                 rv,		apr_strerror(rv, buf, sizeof buf));        exit(1);    }    switch(socket_mode) {    case BLK:        /* leave it blocking */        break;    case NONBLK:        /* set it non-blocking */        rv = apr_socket_opt_set(sock, APR_SO_NONBLOCK, 1);        if (rv != APR_SUCCESS) {            fprintf(stderr, "apr_socket_opt_set(APR_SO_NONBLOCK)->%d/%s\n",                     rv,                    apr_strerror(rv, buf, sizeof buf));            exit(1);        }        break;    case TIMEOUT:        /* set a timeout */        rv = apr_socket_timeout_set(sock, 100 * APR_USEC_PER_SEC);        if (rv != APR_SUCCESS) {            fprintf(stderr, "apr_socket_opt_set(APR_SO_NONBLOCK)->%d/%s\n",                     rv,                    apr_strerror(rv, buf, sizeof buf));            exit(1);        }        break;    default:        assert(1 != 1);    }    printf("Sending the file...\n");    hdtr.headers = headers;    hdtr.numheaders = 3;    hdtr.headers[0].iov_base = HDR1;    hdtr.headers[0].iov_len  = strlen(hdtr.headers[0].iov_base);    hdtr.headers[1].iov_base = HDR2;    hdtr.headers[1].iov_len  = strlen(hdtr.headers[1].iov_base);    hdtr.headers[2].iov_base = malloc(HDR3_LEN);    assert(hdtr.headers[2].iov_base);    memset(hdtr.headers[2].iov_base, HDR3_CHAR, HDR3_LEN);    hdtr.headers[2].iov_len  = HDR3_LEN;    hdtr.trailers = trailers;    hdtr.numtrailers = 3;    hdtr.trailers[0].iov_base = TRL1;    hdtr.trailers[0].iov_len  = strlen(hdtr.trailers[0].iov_base);    hdtr.trailers[1].iov_base = TRL2;    hdtr.trailers[1].iov_len  = strlen(hdtr.trailers[1].iov_base);    hdtr.trailers[2].iov_base = malloc(TRL3_LEN);    memset(hdtr.trailers[2].iov_base, TRL3_CHAR, TRL3_LEN);    assert(hdtr.trailers[2].iov_base);    hdtr.trailers[2].iov_len  = TRL3_LEN;    expected_len =         strlen(HDR1) + strlen(HDR2) + HDR3_LEN +        strlen(TRL1) + strlen(TRL2) + TRL3_LEN +        FILE_LENGTH;        if (socket_mode == BLK) {        current_file_offset = 0;        len = FILE_LENGTH;        rv = apr_socket_sendfile(sock, f, &hdtr, &current_file_offset, &len, 0);        if (rv != APR_SUCCESS) {            fprintf(stderr, "apr_socket_sendfile()->%d/%s\n",                    rv,                    apr_strerror(rv, buf, sizeof buf));            exit(1);        }                printf("apr_socket_sendfile() updated offset with %ld\n",               (long int)current_file_offset);                printf("apr_socket_sendfile() updated len with %ld\n",               (long int)len);                printf("bytes really sent: %" APR_SIZE_T_FMT "\n",               expected_len);        if (len != expected_len) {            fprintf(stderr, "apr_socket_sendfile() didn't report the correct "                    "number of bytes sent!\n");            exit(1);        }    }    else {        /* non-blocking... wooooooo */        apr_size_t total_bytes_sent;        pfd = NULL;        rv = apr_poll_setup(&pfd, 1, p);        assert(!rv);        rv = apr_poll_socket_add(pfd, sock, APR_POLLOUT);        assert(!rv);        total_bytes_sent = 0;        current_file_offset = 0;        len = FILE_LENGTH;        do {            apr_size_t tmplen;            tmplen = len; /* bytes remaining to send from the file */            printf("Calling apr_socket_sendfile()...\n");            printf("Headers (%d):\n", hdtr.numheaders);            for (i = 0; i < hdtr.numheaders; i++) {                printf("\t%ld bytes (%c)\n",                       (long)hdtr.headers[i].iov_len,                       *(char *)hdtr.headers[i].iov_base);            }            printf("File: %ld bytes from offset %ld\n",                   (long)tmplen, (long)current_file_offset);            printf("Trailers (%d):\n", hdtr.numtrailers);            for (i = 0; i < hdtr.numtrailers; i++) {                printf("\t%ld bytes\n",                       (long)hdtr.trailers[i].iov_len);            }            rv = apr_socket_sendfile(sock, f, &hdtr, &current_file_offset, &tmplen, 0);            printf("apr_socket_sendfile()->%d, sent %ld bytes\n", rv, (long)tmplen);            if (rv) {                if (APR_STATUS_IS_EAGAIN(rv)) {                    assert(tmplen == 0);                    nsocks = 1;                    tmprv = apr_poll(pfd, 1, &nsocks, -1);                    assert(!tmprv);                    assert(nsocks == 1);                    /* continue; */                }            }            total_bytes_sent += tmplen;            /* Adjust hdtr to compensate for partially-written             * data.             */            /* First, skip over any header data which might have             * been written.             */            while (tmplen && hdtr.numheaders) {                if (tmplen >= hdtr.headers[0].iov_len) {                    tmplen -= hdtr.headers[0].iov_len;                    --hdtr.numheaders;                    ++hdtr.headers;                }                else {                    hdtr.headers[0].iov_len -= tmplen;                    hdtr.headers[0].iov_base = 			(char*) hdtr.headers[0].iov_base + tmplen;                    tmplen = 0;                }            }            /* Now, skip over any file data which might have been             * written.             */            if (tmplen <= len) {                current_file_offset += tmplen;                len -= tmplen;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -