Linux下实现Post方式

2023-05-16

首先了解HTTP协议各字段的含义,以下是部分较好的归纳:
HTTP一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成。

 (1)请求行
请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如,GET /index.html HTTP/1.1。
HTTP协议的请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。这里介绍最常用的GET方法和POST方法。
GET:当客户端要从服务器中读取文档时,使用GET方法。GET方法要求服务器将URL定位的资源放在响应报文的数据部分,回送给客户端。使用GET方法时,请求参数和对应的值附加在URL后面,利用一个问号(“?”)代表URL的结尾与请求参数的开始,传递参数长度受限制。例如,/index.jsp?id=100&op=bind。
POST:当客户端给服务器提供信息较多时可以使用POST方法。POST方法将请求参数封装在HTTP请求数据中,以名称/值的形式出现,可以传输大量数据,可用来传送文件。
(2)请求头部
请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:
User-Agent:产生请求的浏览器类型。
Accept:客户端可识别的内容类型列表。
Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
(3)空行
最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
对于一个完整的http请求来说空行是必须的,否则服务器会认为本次请求的数据尚未完全发送到服务器,处于等待状态。
(4)请求数据
请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。
一、Post访问

1、程序分析:

使用socket 编程实现Post访问网页,以TCP协议绑定。

代码如下:


CHTTPClient.hpp:

#ifndef SRC_HTTPCLIENT_HPP
#define SRC_HTTPCLIENT_HPP

#include <netinet/in.h>
#include <sys/socket.h>

typedef struct _httpInfo
{
    int socket;
    int connected;
    int remote_port;
    std::string remote_ip;
    struct sockaddr_in _addr;
} HTTPInfo;

class CHTTPClient
{
public:

    int HTTPClientCreate(HTTPInfo& http);
    int HTTPClientConnect(HTTPInfo& http);
    int HTTPClientSend(const HTTPInfo& http, char *buff, int length);
    int HTTPClientReceive(const HTTPInfo& http, char **lpbuff);
    int HTTPClientClose(HTTPInfo& http);
    int HTTPPost(HTTPInfo& http, char *page, char* type, char *request, long request_len, char **response);
}; //class CHTTPClient

#endif  //SRC_HTTPCLIENT_HPP




CHTTPClient.cpp:

int CHTTPClient::HTTPClientCreate(HTTPInfo& http)
{
    NGILog_Trace("func = %s begins", __FUNCTION__);
    struct hostent *he;

    if (NULL == (he = gethostbyname(http.remote_ip.c_str())))
    {
        NGILog_Error("func = %s ends, hostent pointer is null!", __FUNCTION__);
        return -1;
    }

    char ip[17];
    strcpy(ip, inet_ntoa(*((struct in_addr *) he->h_addr) ));

    http.remote_ip = ip;
    http.connected = 0;
    http._addr.sin_family = AF_INET;
    http._addr.sin_port = htons(http.remote_port);
    http._addr.sin_addr = *((struct in_addr *) he->h_addr);

    if (-1 == (http.socket = socket(AF_INET, SOCK_STREAM, 0)))
    {
        NGILog_Error("func = %s ends, create socket fail!", __FUNCTION__);
        return -2;
    }

    NGILog_Trace("func = %s ends, create socket instance is successful!", __FUNCTION__);
    return 0;
}

int CHTTPClient::HTTPClientConnect(HTTPInfo& http)
{
    NGILog_Trace("func = %s begins", __FUNCTION__);

    if (!http.connected)
    {
        if (connect(http.socket, (struct sockaddr *) &http._addr, sizeof(struct sockaddr)) == -1)
        {
            NGILog_Error("func = %s ends, HTTP client is connect error!", __FUNCTION__);
            return -1;
        }

        http.connected = 1;
    }
    else
    {
        NGILog_Trace("func = %s ends, HTTP client is already existed!", __FUNCTION__);
    }

    NGILog_Trace("func = %s ends, connect socket is successful!", __FUNCTION__);
    return 0;
}

int CHTTPClient::HTTPClientSend(const HTTPInfo& http, char *buff, int length)
{
    NGILog_Trace("func = %s begins, the size of the buffer is %d, buffer data:\n%s", __FUNCTION__, length, buff);

    int bytes_left = length;
    int sent_bytes = 0;
    char *ptr = buff;

    while (bytes_left > 0)
    {
        sent_bytes = send(http.socket, ptr, bytes_left, 0);
        if (sent_bytes <= 0)
        {
            if (errno == EINTR)
            {
                NGILog_Warning("func = %s , interrupts were generated!", __FUNCTION__);
                sent_bytes = 0;
            }
            else
            {
                NGILog_Error("func = %s ends, send data error!", __FUNCTION__);
                return -1;
            }
        }
        bytes_left -= sent_bytes;
        ptr += sent_bytes;
    }

    NGILog_Trace("func = %s ends, send data finish!", __FUNCTION__);
    return 0;
}

int CHTTPClient::HTTPClientReceive(const HTTPInfo& http, char **lpbuff)
{
    NGILog_Trace("func = %s begins", __FUNCTION__);

    int bytes_recv = 0;
    int bytes_buff = 0;
    char buff[BUFFER_SIZE+1];

    *lpbuff = NULL;

    while (1)
    {
        memset(buff, '\0', sizeof(buff));
        bytes_recv = recv(http.socket, buff, BUFFER_SIZE, 0);
        printf ("func = %s, recv size is %d, buff data:\n%s", __FUNCTION__, bytes_recv, buff);
        //NGILog_Trace("func = %s, recv size is %d", __FUNCTION__, bytes_recv);
        if (bytes_recv < 0)
        {
            if (errno == EINTR)
            {
                NGILog_Warning("func = %s , interrupts were generated!", __FUNCTION__);
                bytes_recv = 0;
            }
            else
            {
                NGILog_Error("func = %s ends, receive data error!", __FUNCTION__);
                return -1;
            }
        }
        else if (bytes_recv == 0)
        {
            NGILog_Error("func = %s, receive data finish!", __FUNCTION__);
            break;
        }

        bytes_buff += bytes_recv;

        if (*lpbuff == NULL)
        {
            NGILog_Warning("func = %s , interrupts were generated!", __FUNCTION__);
            *lpbuff = (char*) malloc(bytes_buff);
            if (*lpbuff == NULL)
            {
                return -1;
            }
        }
        else
        {
            NGILog_Trace("func = %s, line = %d", __FUNCTION__, __LINE__);
            *lpbuff = (char*) realloc(*lpbuff, bytes_buff);
            if (*lpbuff == NULL)
            {
                return -2;
            }
        }
        memcpy((*lpbuff + bytes_buff - bytes_recv), buff, bytes_recv);
    }

    printf("func = %s ends, the size of the received data is %d!", __FUNCTION__, strlen(*lpbuff));
    return (strlen(*lpbuff));
}



int CHTTPClient::HTTPClientClose(HTTPInfo& http)
{
    NGILog_Trace("func = %s begins", __FUNCTION__);

    close(http.socket);
    http.connected = 0;

    NGILog_Trace("func = %s ends, close socket finish!", __FUNCTION__);
    return 0;
}

int CHTTPClient::HTTPPost(HTTPInfo& http, char *page, char* type, char *request, long request_len, char **response)
{
    NGILog_Trace("func = %s begins", __FUNCTION__);

    char *lpbuf = NULL;
    char post[strlen(page) + 20], host[http.remote_ip.size() + 20], content_type[strlen(type) + 20], content_len[50];
    memset(post, '\0', sizeof(post));
    memset(host, '\0', sizeof(host));
    memset(content_type, '\0', sizeof(content_type));
    memset(content_len, '\0', sizeof(content_len));

    sprintf(post, "POST %s HTTP/1.1\r\n", page);
    sprintf(host, "HOST: %s:%d\r\n", http.remote_ip.c_str(), http.remote_port);
    sprintf(content_type, "Content-Type: %s\r\n", type);
    sprintf(content_len, "Content-Length: %ld\r\n\r\n", request_len);

    int len = strlen(post) + strlen(host) + strlen(content_type) + strlen(content_len) + request_len + 1;
    char send_data[len];
    memset(send_data, '\0', sizeof(send_data));
    memcpy(send_data, post, strlen(post));
    memcpy(&send_data[strlen(post)], host, strlen(host));
    memcpy(&send_data[strlen(post) + strlen(host)], content_type, strlen(content_type));
    memcpy(&send_data[strlen(post) + strlen(host) + strlen(content_type)], content_len, strlen(content_len));
    memcpy(&send_data[strlen(post) + strlen(host) + strlen(content_type) + strlen(content_len)], request, request_len);
 
    if (HTTPClientCreate(http))
    {
        NGILog_Error("func = %s ends, create socket instance error!", __FUNCTION__);
        return -1;
    }

    if (!http.connected)
    {
        if (HTTPClientConnect(http))
        {
            NGILog_Error("func = %s ends, connect socket error!", __FUNCTION__);
            return -2;
        }
    }

    if (HTTPClientSend(http, send_data, len) < 0)
    {
        NGILog_Error("func = %s ends, send data error!", __FUNCTION__);
        return -3;
    }

    /*it's time to receive data from server*/
    if (HTTPClientReceive(http, response) <= 0)
    {
        NGILog_Error("func = %s ends, receive data error!", __FUNCTION__);
        return -4;
    }

    HTTPClientClose(http);

    printf("func = %s ends, post data is finish, response data:\n%s", __FUNCTION__, *response);
//    NGILog_Trace("func = %s ends, post data is finish, response data:\n%s", __FUNCTION__, *response);
    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux下实现Post方式 的相关文章

随机推荐

  • cmake管理子程序,lib库和so库应用实践

    cmake在管理大型项目时经常被用到 xff0c 本文以简单程序演示来说明camke管理项目应用 xff0c 其中包括主程序 xff0c 子程序 xff0c so库程序 xff0c lib程序 目录 1 程序目录结构 2 编译执行 3 清除
  • GIt常用命令总结

    目录 1 创建新建分支 2 强制拉去代码 3 合并相邻提交 xff0c 保证只有一个commit信息 4 本地回退 5 查看git修改列表 6 提交代码 7 切换新分支并从服务端拉取最新 8 git cherry pick合并代码使用 9
  • Linux 下I/O多路复用总结

    xfeff xfeff select xff0c poll xff0c epoll都是IO多路复用的机制 I O多路复用就通过一种机制 xff0c 可以监视多个描述符 xff0c 一旦某个描述符就绪 xff08 一般是读就绪或者写就绪 xf
  • WAV文件头分析

    WAV语音文件头部含有44字节的标志信息 xff0c 其含义如下 xff1a ckid xff1a 4字节 RIFF 标志 xff0c 大写 wavHeader 0 61 39 R 39 wavHeader 1 61 39 I 39 wav
  • Linux环境下限制网速和取消限制网速

    查看网卡信息 ip addr root 64 rabbitmq01 ip addr 1 lo lt LOOPBACK UP LOWER UP gt mtu 65536 qdisc noqueue state UNKNOWN qlen 1 l
  • Linux 网络编程2 TCP并发服务器

    Linux 网络编程学习 TCP IP网络编程2 TCP多线程服务器TCP多进程服务器 在前面TCP网络编程代码的基础上进行改造 xff0c 实现并发服务器功能 TCP多线程服务器 实现功能 xff1a server端可以绑定在任意IP端s
  • HTTP Digest authentication

    什么是摘要认证 摘要认证 xff08 Digest authentication xff09 是一个简单的认证机制 xff0c 最初是为HTTP协议开发的 xff0c 因而也常叫做HTTP摘要 xff0c 在RFC2617中描述 其身份验证
  • 简单的netfilter hook函数注册以及内核链表的使用

    include lt linux netfilter h gt include lt linux init h gt include lt linux module h gt include lt linux netfilter ipv4
  • 详述GPS原理及RTK技术应用

    完整的PPT文档在这里 xff1a 详述GPS原理及RTK技术应用 1 GPS概述 1 1定义 全球定位系统GPS xff08 Global Position System xff09 xff0c 全称为NAVSTAR GPS xff08
  • PHP HTTP Digest校验

    PHP作为客户端进行HTTP Digest校验 span class token comment 请求方法 span span class token variable username span span class token oper
  • Http Digest认证协议

    其认证的基本框架为挑战认证的结构 xff0c 如下图所示 xff1a xfeff xfeff 1 客户端希望取到服务器上的某个资源 xff0c 向服务器发送Get请求 2 服务器收到客户端的请求后 xff0c 发现这个资源需要认证信息 xf
  • Postman 安装

    Postman 的下载安装 Postman是一个用于构建和使用API的API平台 xff08 接口的调试工具 xff09 选择对应的系统和版本进行下载 https github com hlmd Postman cn 这里我的电脑是wind
  • 【安卓自定义控件系列】自绘控件打造界面超炫功能超强的圆形进度条

    在前面我们讲过了安卓自定义控件三种方式中的组合控件 xff0c 现在我们来讲解一下通过自绘的方式来实现自定义控件 xff0c 本博客将以自定义圆形进度条为例向大家讲解自定义控件的知识 xff0c 首先来看一下效果图吧 xff0c 这个是本人
  • Linux网络编程3——多进/线程并发服务器

    视频链接 黑马程序员 Linux网络编程 哔哩哔哩 bilibili https www bilibili com video BV1iJ411S7UA p 61 37 目录 一 高并发服务器 1 1 图示 1 2 分类 二 多进程并发服务
  • http请求头和响应头

    文章目录 参考HTTP通用标头Cache ControlConnectionDatePragmaTrailerTransfer EncodingUpgradeViaWarning 请求头AcceptAccept RangesAccept E
  • C++如何使用libcurl发送post请求的三种content-type的封装

    作者 xff1a 虚坏叔叔 博客 xff1a https xuhss com 早餐店不会开到晚上 xff0c 想吃的人早就来了 xff01 x1f604 C 43 43 如何使用libcurl发送post请求的三种content type的
  • 开源四轴飞行器CC3D的稳定模式和PID算法简介

    本文主要介绍一下CC3D的两大飞行模式的原理 xff1a 1 Rate 2 Attitude 以及PID的基本原理 至于AxisLock模式及Manual xff0c 日后续说 笔者是CC3D开源飞控入门玩家 xff0c 遇到过不少磕磕碰碰
  • 了解git分支和版本管理

    0 Git分支和标签的命名规范 1 分支 dev test pre pro 即master 2 标签 Tag格式 xff1a 主版本号 次版本号 修订号 类型标签 xff0c 其中类型标签可为 xff1a alpha beta rc r T
  • ubuntu下解决高并发socket最大连接数限制,tcp默认1024个连接

    nux系统默认ulimit为1024个访问 用户最多可开启的程序数目 一般一个端口 xff08 即一个进程 xff09 的最高连接为2的16次方65536 通过这个命令 ulimit n 可以看到默认值为1024 查看全局文件句柄数限制 系
  • Linux下实现Post方式

    首先了解HTTP协议各字段的含义 xff0c 以下是部分较好的归纳 xff1a HTTP一个HTTP请求报文由请求行 xff08 request line xff09 请求头部 xff08 header xff09 空行和请求数据4个部分组