* 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

linux C++ socket 实例 http客户端_#include