http协议(协议发送接收格式)

目录

1.URL

1.1 作用

1.2 格式

1.3 URL转码

2.http协议格式

2.1 http请求格式

2.2 http响应格式

2.3 解释

3.http实现网络通信

2.1 网络通信部份

2.2 服务端


1.URL

1.1 作用

IP和找到网络中的主机,IP+端口号可以找到网络中的唯一进程,而URL就是用来确定全网中唯一资源的。

我们所请求的,html,css,js,视频,音频,标签等都称之为资源。网络资源一定存在于全网中一台Linux主机上,Linux和其他OS保存资源的方式都是以文件的形式保存的,单Linux系统表示一个唯一资源的方式就是使用路径。而路径可以视同目录名加分隔符来表示。

1.2 格式

URL的格式为:

通过观察格式,我们发现IP是以域名的方式来呈现的,比如baidu.com,并不是我们所熟悉的点分字符串的形式。

我们可以使用ping指令来查看网络IP的地址。

ping baidu.com

1.3 URL转码

对于URL来说,之所以要进行编码,是因为URL中有些字符会引起歧义。例如,URL参数字符串中如果包含“&”或者“%”势必会造成服务器解析错误,所以需要对其进行编码。

比如当我们在百度中搜索C++的时候,我们发现URL是这样的

https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=39042058_40_oem_dg&wd=C%2B%2B&oq=git%2520%25E5%25A6%2582%25E4%25BD%2595%25E6%2592%25A4%25E5%259B%259E%2520add%2520%25E5%2590%258E%25E7%259A%2584%25E5%2586%2585%25E5%25AE%25B9&rsv_pq=dbd6b18c0002a868&rsv_t=8d8586cQ7TtJ7g6Lpo5h3LX82MkY700UrFzJARkUDUY0On5%2Bh7Hm0tLe9aSlkX2UKy0%2FKJqUBLFd&rqlang=cn&rsv_dl=tb&rsv_enter=1&rsv_sug3=6&rsv_sug1=5&rsv_sug7=101&rsv_sug2=0&rsv_btype=t&inputT=2998&rsv_sug4=2998

这些都是进行转码之后的结果,我们需要关注其中一点:wd

它表示的是我们的搜索内容,可以看到这里的wd=C%2B%2B,%2B表示的就是一个+。

转移规则如下:将需要转码的字符串转成16进制,然后从右到左取四位(不足四位的直接处理),每两位为一位,前面加上%,编码成%XY格式。

还可以使用转码工具来查看。

通常来说,浏览器会自动进行编码,服务器收到后可能会自己进行解码。

2.http协议格式

无论是请求还是响应,基本上http都是按照行为单位进行构建请求或者相应的!无论是请求还是响应都由四部分构成。用户的上网方式其实就是从目标服务器拿到想要的资源,向目标服务器传输数据,本质上在进行IO操作。

2.1 http请求格式

2.2 http响应格式

2.3 解释

其中请求方法有很多,可以是Get等,http的版本有1.1等,状态码我们比较常见的就是404,对该状态码的解释是not fount。

http解包的方式:一行一行读取,知道读到空行,表示之前的都是报头,下面的是报文。

http协议的传送方式:将整个结构看成一个大字符串:xxxx\yyyy\nzzzz\n,空行是一个特殊的字符,通过空行可以将常字符串一分为二。

http如何分用:分用不是http解决的,是具体的应用代码解决的,http需要有接口帮助上层获得参数。

3.http实现网络通信

2.1 网络通信部份

http的传输层协议使用TCP:

#include<iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<unistd.h>
using namespace std;
struct Sock
{
public:
static int Socket()
{
    int sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        cerr<<"socket error"<<endl;
        return -1;
    }
    return sock;
}
static void Bind(int sock,uint16_t port)
{
    sockaddr_in local;
    local.sin_family=AF_INET;
    local.sin_port=htons(port);
    local.sin_addr.s_addr=INADDR_ANY;
    if((bind(sock,(struct sockaddr*)&local,sizeof(local)))<0)
    {
        cerr<<"bind error"<<endl;
        exit(-2);
    }
}
static void Listen(int sock)
{
    if(listen(sock,5)<0)
    {
        cerr<<"listen error"<<endl;
        exit(-3);
    }
}
static int Accept(int sock)
{
    sockaddr_in peer;
    socklen_t len=sizeof(peer);
    int new_sock=accept(sock,(struct sockaddr*)&peer,&len);
    if(new_sock<0)
    {
        cerr<<"accept error"<<endl;
        exit(-4);
    }
    else
    {
        return new_sock;
    }
}
static void Connect(int sock,uint16_t port,string ip)
{
    sockaddr_in server;
    server.sin_family=AF_INET;
    server.sin_port=htons(port);
    server.sin_addr.s_addr=inet_addr(ip.c_str());
    if((connect(sock,(struct sockaddr*)&server,sizeof(server)))==0)
    {
        cout<<"connect success"<<endl;
    }
    else
    {
        cout<<"connect fail"<<endl;
    }
}
};

2.2 服务端

#include"Sock.hpp"
using namespace std;
void Usage(string proc)
{
    cout<<proc<<" port"<<endl;
}
void* HandlerHttpRequest(void* args)
{
    int sock=*(int*)args;
    delete(int*)args;
    pthread_detach(pthread_self());
    char buffer[1024];
    memset(buffer,0,sizeof(buffer));
    ssize_t s=recv(sock,buffer,sizeof(buffer),0);
    if(s>0)
    {
        cout<<buffer;
    }
    close(sock);
    return nullptr;
}
int main(int argc,char* argv[])
{
    if(argc!=2)
    {
        Usage(argv[0]);
        return -1;
    }
    uint16_t port=atoi(argv[1]);
    int listen_sock=Sock::Socket();
    Sock::Bind(listen_sock,port);
    Sock::Listen(listen_sock);
    while(true)
    {
        int sock=Sock::Accept(listen_sock);
        if(sock>0)
        {
            pthread_t tid;
            int* pram=new int(sock);
            pthread_create(&tid,nullptr,HandlerHttpRequest,(void*)pram);
        }
    }
}

由于没有具体内容,因此空行下的数据层没有内容。

在KV行中,Host代边访问主机,Connection表示连接类型,Cache_Sonrtrol表示缓冲信息,

Usr_agent表示客户端一些信息。

我们可以让服务端来为客户端进行响应:

    std::string http_response = "http/1.0 200 OK\n";
    http_response += "Content-Type: text/plain\n"; // text/plain,正文是普通的文本
    http_response += "\n";                         //空行
    http_response += "hello Chrome";
    send(sock,http_response.c_str(),http_response.size(),0);

此时再用浏览器访问我们的服务器,就可以得到这样一行文本:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值