HTTP协议

URL

URL:统一资源定位符,它是一种特殊类型的URI,包含了用于查找某个资源的足够的信息。
URL由三部分组成:资源类型、存放资源的主机域名、资源文件名。
URL的一般语法格式为:(带方括号[]的为可选项):
  http://hostname[:port][path]
  http表示通过http协议来定位网络资源,hostname表示合法的主机域名或IP地址。port指定一个端口号,为空则使用缺省端口80,path指定请求资源的路径,如果URL中没有给出path,那么浏览器会自动会加上“/”,表示web根目录。

如:
http://www.baidu.com
经过浏览器之后就会变成:
http://www.baidu.com/
带参的URL如下:
http://www.baidu.com/?a=10&b=20
其中“?”表示参数的开始,每个参数都是name=value的形式,每个参数之间以“&”分隔。

HTTP请求

http请求是由请求行、消息报头、空行、请求正文组成。

请求行:method、url、http协议版本
消息报头:名字、冒号、空格、值组成http消息报头(name: value)
空行:必须要有一个空行,以确定消息报头的长度(空行实际上也是一种避免粘包的策略,因为我们知道,第一行是请求行,从第二行开始一直到空行就是消息报头了)
请求正文:…

注: HTTP请求的格式至少要包含一个请求行和一个空行。

method:表示请求方法

  • GET :请求获取Request-URl所标识的资源
  • POST :在Request-URl所标识的资源后附加新的数据
  • HEAD :请求获取由Request-URl所标识的资源的响应消息报头
  • PUT :请求获取由Request-URl所标识的资源的响应消息报头
  • DELETE :请求服务器删除Request-URl作为其标识
  • TRACE :请求服务器或回送收到的请求信息,用于测试或诊断
  • CONNECT :保留将来使用
  • OPTIONS :请求查询服务器的性能,或者查询与资源相关的选项和需求

url:表示请求资源的路径,如果是GET方法的话,可以带有参数。它的值也就是URL中的path。如果是post的方法的话,它的参数在消息正文中。

请求

HTTP响应

http响应是由状态行、消息报头、空行、响应正文组成。

状态行:http协议版本、状态码、状态码描述
消息报头:name: value
空行
响应正文:…

状态码:

  • 1xx:指示信息。表示请求已接受,继续处理
  • 2xx:成功。表示请求被成功接收、理解、接受
  • 3xx:重定向。要完成请求必须进行更进一步的操作
  • 4xx:客户端错误。请求语法有错误,或请求无法实现
  • 5xx:服务器端错误。服务器未能实现合法的请求

常见状态码:
200 OK //客户端请求成功
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Nto Found //请求资源不存在,也就是输入了错误的URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请

响应

HTTP的特点

  1. 支持客户/服务器模式(c/s 或 b/s)

  2. 简单快速:客户向服务器请求服务的时候,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP服务器程序规模小,因而通信速度很快。

  3. 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。

  4. 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答之后即断开连接。采用这种方式可以减少传输时间。

  5. 无状态:HTTP协议是无状态协议。无状态是指协议对事物处理没有记忆能力。缺少状态的话意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次链接传送的数据量增大。另一方面,服务器不需要先前信息时它应答就比较快。

简单的HTTP服务器

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;

void PackageResponse(char http_resp[]){
    int cur_len = 0;
    const char* html = "<html><h2>hello</h2></html>";
    cur_len += sprintf(http_resp, "HTTP/1.1 200 OK\n");
    cur_len += sprintf(http_resp + cur_len, "Content-Length: %lu\n",strlen(html));
    cur_len += sprintf(http_resp + cur_len, "\n");
    cur_len += sprintf(http_resp + cur_len, "%s", html);
}

int main(int argc, char* argv[]){
    if(argc != 3){
        printf("Usage ./server [ip] [port]\n");
        return 1;
    }
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd < 0){
        perror("socket");
        return 1;
    }
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    addr.sin_port = htons(atoi(argv[2]));

    int ret = bind(fd, (sockaddr*)&addr, sizeof(addr));
    if(ret < 0){
        perror("bind");
        return 1;
    }

    ret = listen(fd, 5);
    if(ret < 0){
        perror("listen");
        return 1;
    }

    while(1){
        sockaddr_in peer_addr;
        socklen_t len = sizeof(peer_addr);
        int new_fd = accept(fd, (sockaddr*)&peer_addr, &len);
        if(new_fd < 0){
            perror("accept");
            continue;
        }
        char buf[100 * 1024] = {0};
        ssize_t read_size = read(new_fd, buf, sizeof(buf) - 1);
        if(read_size < 0){
            perror("read");
            close(new_fd);
            continue;
        }
        if(read_size == 0){
            close(new_fd);
            continue;
        }
        buf[read_size] = '\0';
        printf("[Request]\n%s\n", buf);

        char http_resp[100 * 1024] = {0};
        PackageResponse(http_resp);

        write(new_fd, http_resp, strlen(http_resp));
        close(new_fd);
    }
    return 0;
}

最后的效果是在网页上显示hello
响应

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值