linux C++ socket 实例 http客户端

* CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyThread)

set(CMAKE_CXX_STANDARD 11)

add_executable(MyThread main.cpp
        # SysInfo.cpp SysInfo.h
        HttpRequest.cpp HttpRequest.h)

* HttpRequest.h

#ifndef MYTHREAD_HTTPREQUEST_H
#define MYTHREAD_HTTPREQUEST_H

#ifndef ssize_t
typedef signed long ssize_t;
#endif
#ifndef size_t
typedef unsigned long size_t;
#endif

class HttpRequest {
public:
    explicit HttpRequest(unsigned port = 80, unsigned timeout = 30);
    int get(char *content, const char *host, const char *uri, const char *ip);
    int post(char *content, const char *host, const char *uri, const char *ip, const char *data);
    ~HttpRequest();

private:
    /* Read "n" bytes from a descriptor. */
    static ssize_t readn(int fd, void *vptr, size_t n);

    int sockfd;
    unsigned port;
    unsigned timeout;
};


#endif //MYTHREAD_HTTPREQUEST_H

* HttpRequest.cpp

#include "HttpRequest.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <unistd.h>
#include <arpa/inet.h>

HttpRequest::HttpRequest(unsigned int port, unsigned int timeout) {
    this->sockfd = 0;
    this->port = port;
    this->timeout = timeout;
}

int HttpRequest::get(char *content, const char *host, const char *uri, const char *ip) {
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    // sprintf(content, "sockfd=%d\n", sockfd);
    int ret = 0;
    struct sockaddr_in addr{};
    socklen_t addrlen;

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(this->port);
    addr.sin_addr.s_addr = inet_addr(ip);
    addrlen = sizeof(addr);
    ret = connect(sockfd, (struct sockaddr *)(&addr), addrlen);
    if (ret != 0) {
        close(sockfd);
        return errno;
        // delete this;
    }

    char buf[BUFSIZ] = {'\0'};
    size_t n = 0;
    sprintf(buf, "GET %s HTTP/1.0\r\n", uri);
    n = strlen(buf);
    write(sockfd, buf, n);
    memset(buf, 0, n+1);

    sprintf(buf, "Host: %s\r\n", host);
    write(sockfd, buf, strlen(buf));
    memset(buf, 0, BUFSIZ);

    strcpy(buf, "Content-Type: text/html\r\n");
    write(sockfd, buf, strlen(buf));
    memset(buf, 0, BUFSIZ);
    // strcpy(buf, "Accept: */*\r\n");
    write(sockfd, "\r\n\r\n", 4);

    const size_t MAX_PAGE_SIZE = 65535;
    memset(content, 0, MAX_PAGE_SIZE);
    readn(sockfd, content, MAX_PAGE_SIZE);
    close(sockfd);
    sockfd = 0;
    return errno;
}

ssize_t HttpRequest::readn(int fd, void *vptr, size_t n) {
    size_t nleft;
    ssize_t nread;
    char *ptr;

    ptr = static_cast<char *>(vptr);
    nleft = n;
    while (nleft > 0) {
        if ((nread = read(fd, ptr, nleft)) < 0) {
            if (errno == EINTR) {
                nread = 0; /* and call read() again */
            } else {
               return -1;
            }
        } else if (nread == 0) {
            break;  /* EOF */
        } else {}
        nleft -= nread;
        ptr += nread;
    }
    return (ssize_t)(n-nleft);
}

HttpRequest::~HttpRequest() {
    if (this->sockfd != 0) {
        close(this->sockfd);
        this->sockfd = 0;
    }
}

int HttpRequest::post(char *content, const char *host, const char *uri, const char *ip, const char *data) {
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    // sprintf(content, "sockfd=%d\n", sockfd);
    int ret = 0;
    struct sockaddr_in addr{};
    socklen_t addrlen;

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(this->port);
    addr.sin_addr.s_addr = inet_addr(ip);
    addrlen = sizeof(addr);
    ret = connect(sockfd, (struct sockaddr *)(&addr), addrlen);
    if (ret != 0) {
        close(sockfd);
        return errno;
    }
    // sprintf(content, "connect return=%d\n", ret); return 0;

    char buf[BUFSIZ] = {'\0'};
    size_t n = 0;
    sprintf(buf, "POST %s HTTP/1.0\r\n", uri);
    n = strlen(buf);
    write(sockfd, buf, n);
    memset(buf, 0, n+1);

    sprintf(buf, "Host: %s\r\n", host);
    write(sockfd, buf, strlen(buf));
    memset(buf, 0, BUFSIZ);

    sprintf(buf, "UserAgent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1\r\n");
    write(sockfd, buf, strlen(buf));
    memset(buf, 0, BUFSIZ);

    strcpy(buf, "Content-Type: application/x-www-form-urlencoded\r\n");
    write(sockfd, buf, strlen(buf));
    memset(buf, 0, 64);

    size_t len = strlen(data);
    sprintf(buf, "Content-Length: %lu\r\n", len);
    write(sockfd, buf, strlen(buf));
    memset(buf, 0, BUFSIZ);
    write(sockfd, "\r\n", 2);  // header body separator

    write(sockfd, data, len);  // post body
    write(sockfd, "\r\n\r\n", 4);

    ssize_t bytesRead;
    char *p = content;
    int i;
    do {
        memset(buf, 0, 4096);
        // bytesRead = readn(sockfd, buf, 4096);
        bytesRead = read(sockfd, buf, 4096);
        for (i = 0; i < bytesRead; i++) {
            *p = buf[i];
            p++;
        }
        *p = '\0';
    } while (bytesRead > 0);
    return errno;
}

* main.cpp

#include <iostream>
#include <cstring>
// #include "SysInfo.h"
#include "HttpRequest.h"

int main() {
    // std::cout << SysInfo::getEndian() << std::endl;
    char response[65535] = {'\0'};
    HttpRequest request;
//    int ret = request.get(response, "enjoysoft.021city.cn", "/api/sendCode", "121.5.101.32");
#if 1
    int ret = request.post(response, "api.????.com", "/v1/app/send_verify_code",
                           "???.??.10.204", "phone=???????9242&phone_cc=86&tag=CppTest");
#endif
    std::cout << "errno=" << ret << " " << strerror(ret) << "\r\n";
    std::cout << "========\r\n";
    std::cout << response << std::endl;

    return 0;
}

Build:

====================[ Build | MyThread | Debug ]================================
C:\Windows\system32\wsl.exe --distribution Ubuntu --exec /bin/bash -c "export CLION_IDE=TRUE && export CLICOLOR_FORCE=1 && export TERM=xterm && export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' && export JETBRAINS_IDE=TRUE && cd /mnt/e/CLionProjects/MyThread/cmake-build-debug && /usr/bin/cmake --build /mnt/e/CLionProjects/MyThread/cmake-build-debug --target MyThread -- -j 6"
[100%] Built target MyThread

Build finished

Run:

C:\Windows\system32\wsl.exe --distribution Ubuntu --exec /bin/bash -c "cd /mnt/e/CLionProjects/MyThread/cmake-build-debug && /mnt/e/CLionProjects/MyThread/cmake-build-debug/MyThread"
errno=0 Success
========
HTTP/1.1 200 OK
Date: Sun, 12 Mar 2023 03:03:09 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 20
Connection: close
Access-Control-Allow-Headers: Authorization, Cake-Version, *
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 86400000

{"code":0,"data":{}}

Process finished with exit code 0

用socket建立连接请求http接口,必须指定IP地址,可以请求DNS 53端口查询。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

fareast_mzh

打赏个金币

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

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

打赏作者

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

抵扣说明:

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

余额充值