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

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

  • 8
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C语言可以通过使用Socket库来实现HTTP请求。需要进行以下步骤: 1. 创建一个Socket:首先,使用socket()函数创建一个Socket,该Socket将用于与服务器进行通信。可以使用AF_INET作为参数来指定使用IPv4地址族,并使用SOCK_STREAM指定使用TCP协议。 2. 连接到服务器:使用connect()函数将Socket连接到服务器的IP地址和端口号。可以使用gethostbyname()函数来获取服务器的IP地址。 3. 构建HTTP请求使用C语言的字符串操作函数来构建HTTP请求。可以包括请求方法(例如GET或POST),请求头部(例如Host和Content-Type),请求体(对于POST请求),以及其他必要的数据。 4. 发送请求使用send()函数将构建好的HTTP请求发送到服务器。可以使用strlen()函数来获取请求的长度。 5. 接收响应:使用recv()函数从服务器接收HTTP响应。可以先使用recv()接收响应头部,并使用字符串操作函数来解析响应头部信息(例如状态码和响应内容的长度)。然后,根据长度使用recv()继续接收响应内容。 6. 处理响应:根据HTTP响应的格式进行处理。可以根据响应头部的Content-Type来决定如何处理响应内容。 7. 关闭Socket:最后,使用close()函数关闭Socket,释放资源。 需要注意的是,以上步骤只是一个基本的框架,实际实现时可能需要处理异常情况(例如网络连接错误)和进行更复杂的处理(例如使用SSL加密连接)。 总结:使用C语言的Socket库可以实现HTTP请求,通过创建Socket、连接服务器、构建请求发送请求、接收响应、处理响应等步骤来完成HTTP请求和响应的交互。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GeekFong

记录不易,坚持更新

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值