Linux高性能服务器编程6-2

对许多函数还不是很熟悉

这里面使用了iovec,可以避免了将几个字符串再拼接起来,减少开销。

主要思路如下:
1.读取文件
2.设置头文件
3.发送

服务器代码:

#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/uio.h>
#include<fcntl.h>
#define BUFFER_SIZE 1024
static const char* line_stat[2] = {"200 OK", "500 Internal server error"};
int main(int argc, char* argv[]){
    if(argc <= 3){
        printf("ip and port \n");
        return 0;
    }

    char* ip = argv[1];
    int port = atoi(argv[2]);
    char* file_name = argv[3];

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

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

    int ret = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
    assert(ret != -1);

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

    struct sockaddr_in clientaddr;
    socklen_t clientaddr_len;
    int connfd = accept(sockfd, (struct sockaddr*)&clientaddr, &clientaddr_len);
    
    if(connfd < 0){
        printf("errno is : %s \n", errno);
    }else{
        char header_buf[BUFFER_SIZE];
        memset(header_buf, '\0', sizeof(header_buf));

        struct stat file_stat;
        char* file_buffer;

        bool valid = true;
        if(stat(file_name, &file_stat) < 0){//文件不存在
            valid = false;
        }else{
            if(S_ISDIR(file_stat.st_mode)){ //文件是目录
                valid = false;
            }else if(file_stat.st_mode & S_IROTH){ //文件可读
                int fd = open(file_name, O_RDONLY);
                file_buffer = new char[file_stat.st_size + 1];
                memset(file_buffer, '\0', sizeof(file_buffer));
                if(read(fd, file_buffer, file_stat.st_size) < 0){ //读取有问题
                    valid = false;
                }
            }else{
                valid = false;
            }
        }

        int len = 0;
        if(valid){ //如果文件有效
            ret = snprintf(header_buf, BUFFER_SIZE - 1, "%s %s\r\n", "HTTP:/1.1", line_stat[0]);
            len += ret;
            ret = snprintf(header_buf + len, BUFFER_SIZE - 1 - len, "content length : %d\r\n", file_stat.st_size);
            len += ret;
            ret = snprintf(header_buf + len, BUFFER_SIZE - 1 - len, "%s", "\r\n");
            struct iovec iov[2];
            iov[0].iov_base = header_buf;
            iov[0].iov_len = strlen(header_buf);
            iov[1].iov_base = file_buffer;
            iov[1].iov_len = file_stat.st_size;
            writev(connfd, iov, 2);
        }else{
            ret = snprintf(header_buf, BUFFER_SIZE - 1, "%s %s\r\n", "HTTP:/1.1", line_stat[1]);
            len += ret;
            ret = snprintf(header_buf + len, BUFFER_SIZE - 1 - len, "%s", "\r\n");
            send(connfd, header_buf, strlen(header_buf), 0);
        }
        close(connfd);
        delete[] file_buffer;
    }
    close(sockfd);
    return 0;
}

客户端代码:

#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#define BUFFER_SIZE 1024
int main(int argc, char* argv[]){
    if(argc <= 2){
        printf("ip and port and size!!!\n");
        return 0;
    }

    char* ip = argv[1];
    int port = atoi(argv[2]);

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

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

    if((connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr))) < 0){
        printf("connect failure \n");
    }else{
        char buf[BUFFER_SIZE];
        memset(buf, '\0', BUFFER_SIZE);
        int ret;
        while((ret = recv(sockfd, buf, sizeof(buf), 0)) > 0){
            printf("%s", buf);
        }
        
    }
    close(sockfd);
    return 0;
}

运行结果:

服务器
在这里插入图片描述
客户端
在这里插入图片描述
a.txt
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值