HTTP协议实用-底层实现客户端服务端交互流程(socket & bind & listen & accept & 多线程处理业务 & close)

本文深入探讨了HTTP协议在实际应用中的客户端与服务端交互过程,通过socket、bind、listen、accept等关键步骤阐述TCP连接的建立,并讨论了多线程处理业务的策略,最后讲解了如何关闭连接。
摘要由CSDN通过智能技术生成
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <sys/wait.h>
#include <signal.h>

#define SIZE (1024 * 10)
typedef struct http_request{
    //1.创建一段缓冲区,存放首行信息
    char first_line[SIZE];
    //2.http的首行
    //  a)http的请求方法
    char* method;
    //  b)http中的url
    char* url;
    //  c)http的url_path
    char* url_path;
    //  d)http的query_string
    char* query_string;
    //3.http的header部分
    //  丢弃了大多数据,在此只保存Content_length
    int content_length;
}http_request;

int read_line(int64_t handle_fd, char temp[], ssize_t size)
{
    char c = '\0';
    ssize_t i = 0;
    //在不同的平台上换行的表示方式也不同:\r、\n、\r\n
    //那么我们就将这三种统一为\n
    while (i < size - 1 && c != '\n'){
        //1.从socket中一次只读取一个字符
        ssize_t read_size = recv(handle_fd, &c, 1, 0);
        if (read_size < 0){
            perror("recv");
            return -1;
        }
        if (read_size == 0){
            //预期得到\n才退出循环,结果现在读取了0个字符,那么也认为是错误
            perror("recv");
            return -1;
        }
        //2.将不同平台的换行均转换为\n
        if (c == '\r'){
            //当读取的是\r的时候,还要看看下一个字符是不是\n
            //注意:recv的第四个参数是MSG_PEEK的时候,只会将缓冲区中的数据拿出来看一下再放回去
            read_size = recv(handle_fd, &c, 1, MSG_PEEK);
            if (read_size <= 0){
                perror("recv");
                return -1;
            }
            if (c == '\n'){
                //该平台的分隔符是\r\n,现将其转为\n
                //下个字符是\n,那就将它读取出来即可
                recv(handle_fd, &c, 1, 0);
                if (read_size <= 0){
                    perror("recv");
                    return -1;
                }
            }
            else{
                //该平台的分隔符是\r,现将其转为\n
                c = '\n';
            }
        }
        //3.将读取到的数据放入我们http_request的缓冲区中
        temp[i++] = c;
        //4.当前读取的字符是\n就可以停止了
        if (c == '\n'){
            break;
        }
    }
    //这里一定要用\0作为读取的结束标志
    temp[i] = '\0';
    //返回读取这一行所读的字符个数
    return i;
}

int Split(char temp[], const char* split_ch, char* tok[], int tok_size)
{
    //使用strtok字符串切分函数
    //strtok一次只能切分一次,只在第一次调用的时候需传入切分字符串,后面再切分该字符串的时候不需要在传入切分的字符串了
    //这就说明strtok内部肯定维护了一个全局变量去记录要切分的字符串,现在是多线程编程,是不能使用全局数据的
    //那么,还有个和strtok一样功能却是线程安全的函数 --> strtok_r
    //strtok_r不再使用内部的一个静态缓冲区,而是使用参数去记录要切分的字符串缓冲区,这个参数是栈上开辟的就不会出现问题了
    char* point = NULL;
    int i = 0;
    char *pch;
    //1.第一次切分的时候,传入需切分的字符串
    pch = strtok_r(temp, split_ch, &point);
    //2.循环调用strtok进行切分
    while (pch != NULL){
        if (i >&#
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值