C语言实现http post请求和get请求,post请求可以上传图片和文件

2023-05-16

文章目录

    • 1.http协议简介
    • 2.http协议分析
      • 2.1 http请求
        • 2.1.1 请求行
          • 2.1.1.1 请求方法
          • 2.1.1.2 URL
          • 2.1.1.3 协议版本
          • 2.1.1.4 请求行总结
        • 2.1.2 请求头部
        • 2.1.3 请求数据
      • 2.2 http响应
        • 2.2.1 状态行
        • 2.2.2 消息报头
        • 2.2.3 响应正文
    • 3. 代码分析(可在arm平台中直接使用,全c实现)
      • 3.1 tcp基于协议代码
      • 3.2 基于http协议代码和测试用例

1.http协议简介

  http协议叫做超文本传输协议,HTTP是一个基于TCP/IP通信协议来传递数据,本章讲解http的请求和http的响应报文解析

2.http协议分析

  本小节主要讲解http的请求报文和响应报文

2.1 http请求

  http请求主要有请求行,请求头部,空行,和请求数据组成

2.1.1 请求行

  请求行主要有请求方法,url和协议版本组装但是,有严格的格式要求,下面就来具体的解析

2.1.1.1 请求方法

  请求方法主要有:GET方法, post方法,opions ,Put ,Head ,Delete ,Trace 但是这里我们主要讲解的是get方法,和post方法这两种常见的方法。

get方法:

  
get请求通常用于获取服务器资源,也可以提交数据,但是通过url的方式提交数据是极其不安全的,因为数据会直接让人可以看到。例如:Http://127.0.0.1/login.jsp?Name=zhangshi&Age=30, 而且传输的的数据大小会受到限制,因此进行数据提交或者上传文件时,建议用post的请求

post方法:

  
post方法是GET方法的一个替代方法,它主要是向Web服务器提交表单数据,尤其是大批量的数据。post方法克服了GET方法的一些缺点。通过POST方法提交表单数据时,数据不是作为URL请求的一部分而是作为标准数据传送给Web服务器,这就克服了GET方法中的信息无法保密和数据量太小的缺点。因此,出于安全的考虑以及对用户隐私的尊重,通常表单提交时采用POST方法

2.1.1.2 URL

  URL就是统一资源定位器(UniformResourceLocator:URL)。通俗地说,它是用来指出某一项信息的所在位置及存取方式;更严格一点来说,URL就是在WWW上指明通讯协议以及定位来享用网络上各式各样的服务功能。也就是告诉服务器,我要从哪个位置获取你资源

2.1.1.3 协议版本

   http协议有以下版本:

  • HTTP/0.9
  • HTTP/1.0
  • HTTP 1.1
  • HTTP/2.0

   具体各个版本有什么更新就不具体介绍了,此字段主要是想做版本的兼容

2.1.1.4 请求行总结

   http的样例如下:

请求方法 url 协议版本
GET /test HTTP/2.0

2.1.2 请求头部

  请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,常见的有如下

Header解释示例
Accept指定客户端能够接收的内容类型Accept: text/plain,text/html,application/json
Accept-Charset浏览器可以接受的字符编码集Accept-Charset: iso-8859-5
Accept-Encoding指定浏览器可以支持的web服务器返回内容压缩编码类型Accept-Encoding: compress, gzip
Accept-Language浏览器可接受的语言Accept-Language: en,zh
Content-Length请求的内容长度Content-Length: 348
Date请求发送的日期和时间Date: Tue, 15 Nov 2010 08:12:31 GMT
User-AgentUser-Agent的内容包含发出请求的用户信息User-Agent: Mozilla/5.0 (Linux; X11)
Host指定请求的服务器的域名和端口号Host: www.zcmhi.com

实例:

User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi

2.1.3 请求数据

总体实例:

POST /test HTTP/2.0
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi
空行
请求的数据

2.2 http响应

  HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。

2.2.1 状态行

  响应行一般由协议版本、状态码及其描述组成 比如 HTTP/1.1 200 OK

2.2.2 消息报头

  消息报头用于描述服务器的基本信息,以及数据的描述,服务器通过这些数据的描述信息,可以通知客户端如何处理等一会儿它回送的数据,也是键值对的形式存在,常见有以下:

  • Location:这个头通常配合302或307状态码使用,服务器使用这个头告诉浏览器去找谁。
  • Server:服务器通过这个头告诉浏览器,服务器的类型。
  • Content-Encoding: 服务器通过这个头告诉浏览器,数据的压缩格式(gzip)。
  • Content-Length:服务器通过这个头告诉浏览器,回送数据的长度。

2.2.3 响应正文

总体实例:

HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain

响应正文

3. 代码分析(可在arm平台中直接使用,全c实现)

  • 基于tcp协议的代码
  • 基于http协议代码,包括http get请求,post请求,和文件上传三种

3.1 tcp基于协议代码

/*************************************************************************
* @Descripttion: 
* @Version: 0.0.1
* @Author: Xiaofang
* @Date: 2020-08-26 19:14:03
* @LastEditors: Xiaofang
* @LastEditTime: 2020-09-02 23:58:12
  *************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "tcp.h"


#if defined(LINUX)
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <errno.h>
#elif defined(ARM)/*填写ARM相关的socket头文件*/


#endif


/**
  * @name: create_socket
  * @description: 创建socket
  * @note
  * @return 套接字 
  */
int create_socket(void)
{
	int mysfd = socket(AF_INET, SOCK_STREAM, 0); 
	if(mysfd < 0){
		printf("create_socket error = %d\r\n", mysfd);
		return ERROR;
	}

	return mysfd;
}

/**
  * @name: create_connect
  * @description: Tcp连接
  * @note: 传入的必须为ip,没有做域名解析
  * @param sockfd :网络套接字
  * @param host   :ip
  * @param port   :端口
  * @param timeout   :超时时间,按照秒进行计算
  * @return -1:错误 -2超时 大于0正常
  */
int create_connect(int sockfd, char *host, int port, int stimeout)
{
	struct sockaddr_in sAddr;
	struct timeval timeout;
	fd_set fdr, fdw; 
    int  rc;
    int flags;

    
    // 设置非阻塞
    flags = fcntl(sockfd, F_GETFL, 0);
    if(flags < 0){
        printf("Get flags error:%d\n", errno);
        return ERROR;
    }
    
    flags |= O_NONBLOCK;
    if(fcntl(sockfd, F_SETFL, flags) < 0){
        printf("Set flags error:%d\n", errno);
        return ERROR;
    }

	//建立连接
    memset(&sAddr, 0, sizeof(struct sockaddr));
    sAddr.sin_family = AF_INET;
    sAddr.sin_port = htons(port);
    sAddr.sin_addr.s_addr= inet_addr(host);
 
    // 客户端连接,如果大于0表示已经连接成功了,此时不需要做超时判断
    rc = connect(sockfd, (struct sockaddr *)&sAddr, sizeof(sAddr));
    if(rc >= 0){
        goto SUCCESS;
    }else{
        if(errno == EINPROGRESS)
        {
            FD_ZERO(&fdr);
            FD_ZERO(&fdw);
            FD_SET(sockfd, &fdr);
            FD_SET(sockfd, &fdw);
            timeout.tv_sec = stimeout; //通常设置为3
            timeout.tv_usec = 0;
            rc = select(sockfd+1, &fdr, &fdw, NULL, &timeout);
            if(rc > 0)
            {
                //判断套接字是否可读
                if(!FD_ISSET(sockfd, &fdr) && FD_ISSET(sockfd, &fdw)){
                    //printf("http connect ok\r\n");
                    goto SUCCESS;
                }
                
                else if(FD_ISSET(sockfd, &fdr) && FD_ISSET(sockfd, &fdw))
                {
                    socklen_t len = sizeof(rc);
                    if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &rc, &len) < 0){
                        printf("getsockopt error\r\n");
                        return ERROR;
                    }
                    if(rc == 0){
                        goto SUCCESS;  
                    }
                    else{  
                        printf("http timeout,rc:%d\r\n", rc);
                        return TIMEOUT;
                    }
                } 
                
            }
            else if(rc == 0){
                //返回-2代表连接超时
                printf("http connect timeout\r\n");
                return TIMEOUT;
            }
            else{
                printf("http select error\r\n");
                return ERROR;
            }
            
            
            
        }
    }
        
SUCCESS:  
    //设置套接字为阻塞
    flags = fcntl(sockfd, F_GETFL, 0);
    if(flags < 0){
        printf("Get flags error:%d\n", errno);
        return ERROR;
    }
    flags &= ~O_NONBLOCK;
    if(fcntl(sockfd, F_SETFL, flags) < 0){
        printf("Set flags error:%d\n", errno);
        return ERROR;
    }    
  
    return rc;
}


/**
  * @name: socket_send
  * @description: tcp支持发送超时
  * @note: 
  * @param sockfd : socket 套接字
  * @param data : 需要发送的数据
  * @param len : 需要发送数据的长度
  * @param s : 设置超时时间按秒
  * @param us : 设置超时时间按微秒
  * @return 发送了多少个字节
  */
int socket_send(int sockfd, char *data, int len, int s, int us)
{
    //传参判断

    int rc = 0;
    fd_set write_fds;
    struct timeval timeout;
  
    timeout.tv_sec = s;
    timeout.tv_usec = us;   
    
    FD_ZERO(&write_fds);
    FD_SET(sockfd, &write_fds);
    
    rc = select(sockfd+1, NULL, &write_fds, NULL, &timeout);
    if(rc < 0){
        printf("send select error %d\n", rc);
        return ERROR;
    }
    
    if(rc == 0){
        printf("send select timeout\n");
        return TIMEOUT;
    }
    if(rc > 0)
    {
        if(FD_ISSET(sockfd, &write_fds))
        {
            rc = send(sockfd, data, len, 0);
            if(rc < 0)
            {
                printf("socket send error %d\n", rc);
                return ERROR;
            }
        }else{
            printf("FD_ISSET error\n");
            return ERROR;  
        }
    }
    return rc;
}

/**
  * @name: socket_recv
  * @description: tcp支持接收超时
  * @note: 
  * @param sockfd : socket 套接字
  * @param data : 接收数据的缓冲区
  * @param len : 接收数据缓冲区的长度
  * @param s : 设置超时时间按秒
  * @param us : 设置超时时间按微秒
  * @return {type} 
  */
int socket_recv(int sockfd, char *response, int len ,int s, int us)
{

    int rc = 0;
    fd_set read_fds;
    struct timeval timeout;
   

    FD_ZERO(&read_fds);
    FD_SET(sockfd, &read_fds);

    
    timeout.tv_sec = s;
    timeout.tv_usec = us;   
    
    rc = select(sockfd+1, &read_fds, NULL, NULL, &timeout);
    if(rc < 0){
        printf("recv select error\n");
        return ERROR;
    }
    
    if(rc == 0){
        printf("recv select timeout\n");
        return TIMEOUT;
    }

    if(rc > 0)
    {
        if(FD_ISSET(sockfd, &read_fds)){
            rc = recv(sockfd, response, len, 0);
            if(rc < 0){
                printf("recv error %d\n",rc);
                return ERROR;
            }
        }else{
            printf("FD_ISSET error\n");
            return ERROR;  
        }
    }

    return rc;
}
#ifndef __TCP_H__
#define __TCP_H__

/**************************Macro definition***********************************/
/*宏开关,如果是linux平台,定义linux,否则定义ARM*/
#define LINUX
//#define ARM


typedef enum
{
    TIMEOUT = -2, //超时
    ERROR   = -1, //错误
    NORMAL  = 0  //正常
}HttpState_e;


/*************************extern declaration ********************************/
	



/**************************Global variable***********************************/



/**************************Function declaration******************************/

/**
  * @name: create_socket
  * @description: 创建socket
  * @note
  * @return 套接字 
  */
int create_socket(void);

/**
  * @name: create_connect
  * @description: Tcp连接
  * @note: 传入的必须为ip,没有做域名解析
  * @param sockfd :网络套接字
  * @param host   :ip
  * @param port   :端口
  * @param timeout   :超时时间,按照秒进行计算
  * @return -1:错误 -2超时 大于0正常
  */
int create_connect(int sockfd, char *host, int port, int stimeout);


/**
  * @name: socket_send
  * @description: tcp支持发送超时
  * @note: 
  * @param sockfd : socket 套接字
  * @param data : 需要发送的数据
  * @param len : 需要发送数据的长度
  * @param s : 设置超时时间按秒
  * @param us : 设置超时时间按微秒
  * @return 发送了多少个字节
  */
int socket_send(int sockfd, char *data, int len, int s, int us);

/**
  * @name: socket_recv
  * @description: tcp支持接收超时
  * @note: 
  * @param sockfd : socket 套接字
  * @param data : 接收数据的缓冲区
  * @param len : 接收数据缓冲区的长度
  * @param s : 设置超时时间按秒
  * @param us : 设置超时时间按微秒
  * @return {type} 
  */
int socket_recv(int sockfd, char *response, int len ,int s, int us);




#endif

3.2 基于http协议代码和测试用例

/*************************************************************************
* @Descripttion: 
* @Version: 
* @Author: Xiaofang
* @Date: 2020-09-02 23:51:06
* @LastEditors: Xiaofang
* @LastEditTime: 2020-09-03 00:00:58
  *************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h> 
#include <sys/stat.h>
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>
#include "http.h"
#include "tcp.h"

 

int makehttprotocol(HttpParam_t httpparam, char *httppack)
{
    char header[MAX_SIZE_HEARER] = {0};  //需要异常判断大小
    char startmsg[128] = {0}; 
    char endmsg[128] = {0};
    char request[256] = {0};  
    unsigned char http_boundary[64]={0};
    int startboundarylen;
    int endboundarylen;
    int requelen;
    int Content_Length;
    int headerlen;
    int tolsize;

    if(httpparam.method == GET)
    {

        if(httpparam.url == NULL){
            sprintf(httppack, "GET / %s\r\n", HTTP1_1);  
        }else{         
            sprintf(httppack, "GET %s %s\r\n", httpparam.url, HTTP1_1);   
        }

        //请求头: HTTP_DEFAULT_HEADER
        sprintf(httppack, "%s%s\r\n",httppack, HTTP_DEFAULT_HEADER);
        headerlen = sprintf(httppack, "%sHost: %s:%d\r\n",httppack, httpparam.host, httpparam.port);
        if(httpparam.content != NULL)
        {
            sprintf(httppack, "%sContent-Length: %ld\r\n\r\n", httppack, httpparam.picparm.picsize);
        }else{
            sprintf(httppack, "%s\r\n", httppack);
        }
        return httpparam.picparm.picsize+headerlen;
    }
    else if(httpparam.method == POST)
    {
        if(httpparam.ispostpic == 0) //不上传图片,只是简单的post数据
        {
            if(httpparam.url == NULL){      
                sprintf(httppack, "POST / %s\r\n", HTTP1_1);     
            }else{      
                sprintf(httppack, "POST %s %s\r\n", httpparam.url, HTTP1_1);           
            }

            //请求头: HTTP_DEFAULT_HEADER
            sprintf(httppack, "%s%s\r\n",httppack, HTTP_DEFAULT_HEADER);
            headerlen = sprintf(httppack, "%sHost: %s:%d\r\n",httppack, httpparam.host, httpparam.port);
            if(httpparam.content != NULL)
            {
                sprintf(httppack, "%sContent-Length: %ld\r\n\r\n", httppack, httpparam.picparm.picsize);
            }else{
                sprintf(httppack, "%s\r\n", httppack);
            }

            sprintf(httppack, "%s%s\r\n", httppack, httpparam.content);
            return httpparam.picparm.picsize+headerlen;
            
        }
        else if(httpparam.ispostpic == 1) //上传图片
        {

            long long int timestamp;
            struct timeval tv;
            gettimeofday(&tv,NULL);
            timestamp = (long long int)tv.tv_sec * 1000 + tv.tv_usec;
            //1. 获取http_boundary
            sprintf(http_boundary,"----------------------------%lld",timestamp);
            //2. start boundary
            startboundarylen = sprintf(startmsg, "--%s\r\n",http_boundary);
            //3. end boundart
            endboundarylen = sprintf(endmsg, "\r\n--%s--\r\n",http_boundary);
            //4. 
            int requelen = sprintf(request, UPLOAD_REQUEST, httpparam.picparm.picname);
            int Content_Length = requelen + startboundarylen  +  httpparam.picparm.picsize + endboundarylen;
            int headerlen = sprintf(header, HTTP_POST_PIC_HEAD, httpparam.url, httpparam.host, http_boundary, Content_Length);
            int tolsize = Content_Length + strlen(HTTP_POST_PIC_HEAD) + 256; //加256防止溢出

            memcpy(httppack, header, headerlen);
            memcpy(httppack+headerlen, startmsg, startboundarylen);
            memcpy(httppack+headerlen+startboundarylen, request, requelen);
            memcpy(httppack+headerlen+startboundarylen+requelen, httpparam.content, httpparam.picparm.picsize);
            memcpy(httppack+headerlen+startboundarylen+requelen+httpparam.picparm.picsize, endmsg, endboundarylen);

            return tolsize;
        }

    }

 
    return 0;
}



/**
  * @name: http_post
  * @description: 实现http post和get的请求
  * @note: 
  * @param httpparam:http参数结构体
  * @param content:post的内容
  * @param len:内容的长度
  * @param response:获得的响应内容
  * @param resplen:需要获取响应内容大小
  * @return -1错误 -2超时
  */
int http(HttpParam_t httpparam, char *content, int len, char *response, int resplen)
{
    int rc=0;
    int httpfp=0;
    char *httppack;
    httppack = malloc(len+512); //假设http头长度有512,http上传的最终头
    memset(httppack, 0, sizeof(len+512));


    httpfp = create_socket();
    if(httpfp < 0)
    {
        free(httppack);
        return ERROR;

    }

    rc = create_connect(httpfp, httpparam.host, httpparam.port, CONNECTTIMEOUT);
    if(rc < 0)
    {
        free(httppack);
        return rc;
    }

    rc = makehttprotocol(httpparam, httppack);
    if(rc < 0)
    {
        free(httppack);
        return rc;
    }


    rc =  socket_send(httpfp, httppack, rc, httpparam.timeouts, httpparam.timeoutus);
    if(rc < 0)
    {
        free(httppack);
        return rc;
    }
    //此处存在接收不到的情况,可以通过多线程解决,不断的接收数据
    rc = socket_recv(httpfp, response, resplen , httpparam.timeouts, httpparam.timeoutus);
    if(rc < 0)
    {
        free(httppack);
        return rc;
    }

    printf("response = %s\n",response);

    free(httppack);
    return 0;
}

int http_responed(char *respsone)
{
    if(respsone == NULL){
        return -1;
    }
    //1. 判断返回值中是否有200
    int code;
    char *resp;
    resp = strstr(respsone , "\r\n\r\n");
    resp += 4;

    //2. 再获取其返回值内容
    //printf("%s\n", resp);
 /*
    cJSON *root = cJSON_Parse(resp);
    if(root == NULL)
    {
        printf("http respsone is null\n");
    }

    cJSON   *pos;
    pos = cJSON_GetObjectItem(root, "code");
    if(pos != NULL){
            code	= (pos->valueint);
    }else{
            cJSON_Delete(root);
            return -1;
    }      
      
    if(code == 0){
        cJSON_Delete(root);
        return -1;
    }
    cJSON_Delete(root);
*/
    return 0;
}



int main()
{
    HttpParam_t httpparam;
    char responed[1024] = {0};
    memset(httpparam.host, 0, sizeof(httpparam.host));
    memset(httpparam.url, 0, sizeof(httpparam.url));
    strcpy(httpparam.host, "172.16.62.147");
    strcpy(httpparam.url, "/lift/api/uploadFaultPic?id=123123123123 "); //后面的id是我们项目所需要的参数
    strcpy(httpparam.picparm.picname , "123.png");
    httpparam.ispostpic = 1;
    httpparam.port = 80;
    httpparam.method = POST;
    httpparam.timeouts = 1;
    httpparam.timeoutus = 0;
    

    FILE* fp = fopen("123.png", "rb+");							//打开要上传的图片
    if (fp == NULL){  
        printf("open file fail!\r\n");  
        return -1;  
    }

    fseek(fp, 0, SEEK_END);
    httpparam.picparm.picsize = ftell(fp);
    rewind(fp);
    printf("get the size is: %ld\n", httpparam.picparm.picsize);

    
    httpparam.content = malloc(httpparam.picparm.picsize);
    memset(httpparam.content, 0, sizeof(httpparam.picparm.picsize));
    fread(httpparam.content, httpparam.picparm.picsize, 1, fp);


    int re = http(httpparam, httpparam.content, httpparam.picparm.picsize, responed, 1024);
    
    free(httpparam.content);
    //printf("%s\n",content);

    
}
/*
 * @Descripttion: 
 * @Version: 
 * @Author: Xiaofang
 * @Date: 2020-09-02 23:51:17
 * @LastEditors: Xiaofang
 * @LastEditTime: 2020-09-02 23:55:21
 */
#ifndef __HTTP_H__
#define __HTTP_H__


#define CONNECTTIMEOUT 3
#define MAX_SIZE_HEARER 2048

//http版本
#define HTTP1_1 "HTTP/1.1"
#define HTTP2_0 "HTTP/2.0"


//hear普通头
#define HTTP_DEFAULT_HEADER         "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:63.0) Gecko/20100101 Firefox/63.0\r\n"   \
				                    "Connection: keep-alive\r\n" \
                                    "Cache-Control: no-cache\r\n"           \
                                    "Content-Type: application/json\r\n"   \
                                    "Accept: */*"


//http上传文件所需要的头//"enctype: multipart/form-data\r\n"
#define HTTP_POST_PIC_HEAD 	"POST %s HTTP/1.1\r\n"\
                            "User-Agent: PostmanRuntime/7.24.1\r\n"\
                            "Accept: */*\r\n"\
                            "Host: %s\r\n"\
                            "Accept-Encoding: gzip, deflate, br\r\n" \
                            "Connection: keep-alive\r\n" \
                            "Content-Type: multipart/form-data; boundary=%s\r\n"\
                            "Content-Length: %d\r\n\r\n"\

					
					
#define UPLOAD_REQUEST	"Content-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n" \
                        "Content-Type: image/png\r\n\r\n"
					

/**************************Type definition **********************************/


//请求方式
typedef enum {
    GET,
    POST
}RequestMethod_e;

typedef struct 
{
    char picname[32];
    unsigned long picsize;
}PicParm_t;



typedef struct
{
    char host[16];
    char url[128]; //包含参数,参数从url中传入
    int  ispostpic; //是否需要上传图片
    int  port;
    int  method;
    int  timeouts;
    int  timeoutus;
    char *content; //需要申请空间,存放数据
    PicParm_t picparm; //图片参数
}HttpParam_t;



/**************************Function declaration******************************/

int makehttprotocol(HttpParam_t httpparam, char *httppack);

/**
  * @name: http_post
  * @description: 实现http post和get的请求
  * @note: 
  * @param httpparam:http参数结构体
  * @param content:post的内容
  * @param len:内容的长度
  * @param response:获得的响应内容
  * @param resplen:需要获取响应内容大小
  * @return -1错误 -2超时
  */
int http(HttpParam_t httpparam, char *content, int len, char *response, int resplen);


#endif

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

C语言实现http post请求和get请求,post请求可以上传图片和文件 的相关文章

随机推荐

  • 斜线/、反斜线\、双斜线//、双反斜线\\

    看到这些东西就有点小晕 xff0c 整理到一起加以区分 上面符号 xff0c 中为正 xff0c 左为斜线 xff0c 右为反斜 xff1b 八字 xff0c 先撇为斜 xff0c 后捺为反斜 这些符号在不同的系统下意义不同 双斜线 协议和
  • linux中常用的截图录屏软件

    linux中常用的截图录屏软件 1 kazam 推荐 工具小巧而功能全面 可以选择全屏 窗口或者自定义区域 可以设置帧率 编码方式 时延倒计时 音频来源等 kazam默认视频编码方式是H264 保存为MP4文件 还支持截图功能 sudo a
  • openEuler 安装图形桌面环境Gnome或DDE或UKUI

    由于openEuler系统主要针对服务器 xff0c 目前默认安装之后没有图形桌面环境 xff0c 需要的用户可以自己手动安装配置 这里推荐安装深度桌面DDE或优麒麟UKUI环境 安装gnome桌面 sudo dnf makecache s
  • Ubuntu更换国内镜像源

    由于Ubuntu官方镜像速度有限 xff0c 可以使用国内镜像加速更新和下载 xff0c 节约时间 常用的国内镜像有很多 xff0c 本人常用的有如下几个 xff0c 仅供参考 163镜像 mirrors 163 com 清华镜像 mirr
  • ubuntu-2204 gerrit ssh 报错Permission denied (publickey).分析及解决

    ubuntu 2204 gerrit ssh 报错Permission denied publickey 分析及解决 使用repo init sync下载代码时遇到报错 Permission denied publickey 分析排查步骤
  • UCOSII操作系统 第3课—UCOSII启动过程

    1 初始化UCOSII 1 在调用UCOSII在任何的其他的服务之前 xff0c UCOSII要求首先调用初始化函数OSInit 这个函数的目的就是在整个系统启动之前 xff0c 初始化所有的变量和数据结构 2 其中 xff0c 在OSIn
  • vscode安装配置clang-format插件及使用

    vscode安装配置clang format插件及使用 首先安装插件 在vscode扩展里搜索clang format xff0c 安装排名第一的xaver clang format 确认clang format可执行程序路径 window
  • 消息序列化工具-protobuf介绍及安装使用技巧

    简介 protobuf是google团队开发的用于高效存储和读取结构化数据的工具 xml json也可以用来存储此类结构化数据 xff0c 但是使用protobuf表示的数据能更加高效 xff0c 并且将数据压缩得更小 xff0c 大约是j
  • 消息序列化工具-为现代C++设计的jsoncpp介绍与使用技巧

    概述 JSON 的全称为 xff1a JavaScript Object Notation xff0c 顾名思义 xff0c JSON 是用于标记 Javascript 对象的 xff0c JSON 官方的解释为 xff1a JSON 是一
  • cppcheck代码检查工具安装与使用技巧

    cppcheck代码检查工具安装与使用技巧 Cppcheck 是一种 C C 43 43 代码缺陷静态检查工具 不同于 C C 43 43 编译器及很多其它分析工具 xff0c 它不检查代码中的语法错误 Cppcheck 可以检查非标准代码
  • sed流编辑器中使用变量替换以及执行外部命令

    在使用sed对日志或者其它文本进行parse的过程当中 xff0c 有时候我们需要引用外部变量的值 xff0c 或者获取一个shell命令执行的结果 xff0c 以便达到更加可观的输出结果 这里介绍如何做到 sed 流编辑 1 sed命令及
  • mkisofs命令制作iso文件

    mkisofs命令行格式 mkisofs adDfhJlLNrRTvz print size quiet A lt 应用程序ID gt b lt 开机映像文件 gt c lt 开机文件名称 gt hide lt 目录或文件名 gt hide
  • windows下tree命令列出文件目录树

    windows下tree命令列出文件目录树 tree path f tree D AR C Team f 可以将D AR C Team目录下所有目录及子目录下的文件都打印出来 tree D AR C Team f gt HOMEPATH f
  • yum命令安装历史回滚彻底删除安装的依赖包

    yum命令安装一个软件包是会连同依赖包一起安装 xff0c 但是yum remove卸载时却只卸载这个文件包本身 如果需要删除安装时附加的依赖包可以使用yum history的相关操作实现回滚 假如安装了ecliipse pde xff0c
  • latex在ipython jupyter notebook中的使用

    In 2 from IPython display import Latex In 5 数学公式的前后要加上 或 和 Latex r 34 f x 61 3x 43 7 34 Out 5 In 6
  • MATLAB 2018b 帮助页面设置为中文显示

    MATLAB 2018b 帮助页面设置为中文显示 具体步骤如下 xff1a 1 随机点击一个matlab的函数点击 help 2 点击帮助页面的设置按钮 3 按照如下步骤设置即可
  • 图解Java线程死锁的必要条件

    文章目录 What is Deadlock发生死锁要如何解决如何预防死锁参考资料 What is Deadlock In concurrent computing a deadlock is a state in which each me
  • 远程LINUX桌面的好用工具,NoMachine.

    安装及使用都比VNC及XManager要好用 xff0c 网站 https www nomachine com 对应下各自的版本后 xff0c 按照网站的说明进行安装就可以了 xff0c 安装过程不需要其他依赖项 xff01 Linux安装
  • 竞赛经验|2019年电赛B题四旋翼无人机组巡线机器人

    竞赛经验 xff5c 2019年电赛B题四旋翼无人机组巡线机器人 参赛背景和比赛回忆 xff1a 1 院校背景 xff1a 2 规则与现实 xff1a 3 比赛流程 xff1a 备赛建议1 器件选择 xff1a 2 针对学习 xff1a 写
  • C语言实现http post请求和get请求,post请求可以上传图片和文件

    文章目录 1 http协议简介2 http协议分析2 1 http请求2 1 1 请求行2 1 1 1 请求方法2 1 1 2 URL2 1 1 3 协议版本2 1 1 4 请求行总结 2 1 2 请求头部2 1 3 请求数据 2 2 ht