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方式 的相关文章

  • 如何通过保持目录结构完整来同步路径中匹配模式的文件?

    我想将所有文件从服务器 A 复制到服务器 B 这些文件在不同级别的文件系统层次结构中具有相同的父目录名称 例如 var lib data sub1 sub2 commonname filetobecopied foo var lib dat
  • 尝试使用 php 发送 POST 请求,无论我做什么,我都会收到“HTTP ERROR 500”

    为了发出 HTTP 请求 有人建议我尝试使用 PHP 并给了我一段代码 url https example com dashboard api data array to gt PHONE NUMBER from gt SENDER ID
  • 查找哪些页面不再与写入时复制共享

    假设我在 Linux 中有一个进程 我从中fork 另一个相同的过程 后forking 因为原始进程将开始写入内存 Linux写时复制机制将为进程提供与分叉进程使用的不同的唯一物理内存页 在执行的某个时刻 我如何知道原始进程的哪些页面已被写
  • ftrace:仅打印trace_printk()的输出

    是否可以只转储trace printk 输出于trace文件 我的意思是过滤掉函数跟踪器 或任何其他跟踪器 中的所有函数 一般来说 您可以在选项目录中关闭选项 sys kernel debug tracing options Use ls显
  • 查找哪个程序运行另一个程序

    我有一个 NAS 运行在 Redhat Linux 的有限版本上 我按照指示破解了它 这样我就可以访问 shell 这很有帮助 我还做了一些修改 其他人也做过修改 除了一个问题之外 它们似乎都工作得很好 不知何故 每隔 22 天 系统就会关
  • 是否可以创建一个脚本来保存和恢复权限?

    我正在使用 Linux 系统 需要对一组嵌套文件和目录进行一些权限实验 我想知道是否没有某种方法可以保存文件和目录的权限 而不保存文件本身 换句话说 我想保存权限 编辑一些文件 调整一些权限 然后将权限恢复到目录结构中 将更改的文件保留在适
  • “make install”将库安装在 /usr/lib 而不是 /usr/lib64

    我正在尝试在 64 位 CentOS 7 2 上构建并安装一个库 为了这个目的我正在跑步 cmake DCMAKE BUILD TYPE Release DCMAKE INSTALL PREFIX usr DCMAKE C COMPILER
  • 按进程名称过滤并记录 CPU 使用情况

    Linux 下有选项吗顶部命令 https www man7 org linux man pages man1 top 1 html我可以在哪里按名称过滤进程并将每秒该进程的 CPU 使用情况写入日志文件 top pgrep 过滤输出top
  • php exec 返回的结果比直接进入命令行要少

    我有一个 exec 命令 它的行为与通过 Penguinet 给 linux 的相同命令不同 res exec cd mnt mydirectory zcat log file gz echo res 当将命令直接放入命令行时 我在日志文件
  • 如何减去两个 gettimeofday 实例?

    我想减去两个 gettimeofday 实例 并以毫秒为单位给出答案 这个想法是 static struct timeval tv gettimeofday tv NULL static struct timeval tv2 gettime
  • Linux:如何设置进程的时区?

    我需要设置在 Linux 机器上启动的各个进程的时区 我尝试设置TZ变量 在本地上下文中 但它不起作用 有没有一种方法可以使用与系统日期不同的系统日期从命令行运行应用程序 这可能听起来很愚蠢 但我需要一种sandbox系统日期将被更改的地方
  • Urwid:使光标不可见

    我正在使用 urwid 它是一个用于在 ncurses 中设计终端用户界面的 Python 框架 但有一件事我在 urwid 中无法做到 而这在 Curses 中很容易做到 使光标不可见 现在 选择按钮时光标是可见的 而且看起来很丑 有办法
  • Fortran gfortran linux 中的“分段错误(核心转储)”错误

    我正在创建一个程序 该程序将分析目录中的文件 fits 然后它将在另一个目录中创建另一个文件 txt 它只是一个转换器 当我尝试执行该程序 编译正常 时 它给了我一条错误消息 程序收到信号 SIGSEGV 分段错误 无效的内存引用 此错误的
  • Linux 上的基准测试程序

    对于一项任务 我们需要使用不同的优化和参数来对我们的实现进行基准测试 有没有一种可行的方法可以在Linux命令行 我知道时间 上使用不同的参数对小程序进行基准测试 从而为我提供CSV或类似内容的时间数据 输出可能类似于 Implementa
  • 从 systemd bash 内联脚本创建 filename_$(date %Y-%m-%d)

    我正在尝试执行systemd计时器并希望将执行脚本的输出保存在每个日期的文件中 这是我的ExecStart脚本中的 service file ExecStart bin bash c echo date Y m d gt gt home u
  • 当用户按下打印时运行脚本,并且在脚本结束之前不开始假脱机(linux,cups)

    我需要做的是结合用户按下打印来执行 python 程序 脚本 并且在该程序退出之前不要让打印作业假脱机 原因是打印驱动程序不是开源的 我需要更改用户设置 在本例中是部门 ID 和密码 通常是每个用户 但因为这是一个信息亭 具有相同帐户的不同
  • 转义用户数据,无需魔法引号

    我正在研究如何在来自外部世界的数据被用于应用程序控制 存储 逻辑等之前正确地对其进行转义 显然 随着 magic quote 指令在 php 5 3 0 中很快被弃用 并在 php6 中被删除 对于任何想要升级并进入新语言功能 同时维护遗留
  • 每个命令都返回“bash:<命令>:找不到命令...”[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我刚刚安装了 Scala 并添加了路径gedit bashrc export SCALA HOME home avijit sca
  • 如何从 PROC 获取有关子进程的信息

    我正在尝试编写一个以几个进程作为参数的程序 然后父进程执行每个子进程并打印出一些相关的统计信息 示例 generate ls l 将生成一个程序 打印出有关 ls l 的一些统计信息 特别是其系统时间 用户时间和上下文切换次数 我不想使用
  • Gearman,php 扩展问题:使用终端在 .. 中找不到类“GearmanWorker”,但可以在浏览器上使用

    我最近在 ubuntu 10 04 上安装了 gearman 并安装了它的 pecl 扩展 现在 当我在浏览器中运行一个 php 文件时 其中包含 client new GearmanWorker die var Dump client I

随机推荐

  • 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个部分组