C++之Socket简单使用

C++之Socket简单使用

#################################
# CMakeLists.txt 文件内容如下
#################################
cmake_minimum_required(VERSION 3.23)
project(test)
set(CMAKE_CXX_STANDARD 14)
add_executable(test main.cpp)
# 注意此处的 ws2_32(全名:libws2_32.a)该行命令相当于 g++ main.cpp -lws2_32.a 目的是链接 libws2_32.a 库
# 类似的还有 target_link_libraries(test2 pthread) 链接多线程并发动态库 g++ main.cpp -lpthread
target_link_libraries(test ws2_32)

////////////////////////////////////
// main.cpp 文件源码如下
////////////////////////////////////
#include <iostream>
#include <ws2dnet.h>
void sendMsgToClient(SOCKET *clientSocket);
void acceptClient(SOCKET *serverSocket, SOCKET *clientSocket);

int main() {
    WSADATA wsadata;
    WSAStartup(MAKEWORD(2, 2), &wsadata);
    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (serverSocket == INVALID_SOCKET) {
        std::cout << "socket出错" << std::endl;
        return 1;
    } else {
        sockaddr_in sockAddr;   // 创建套接字地址
        memset(&sockAddr, 0, sizeof(sockAddr)); // 用0填充每个字节
        sockAddr.sin_family = PF_INET;  // 使用PF_INET地址族,也就是IPv4
        sockAddr.sin_addr.s_addr = inet_addr("192.168.0.106");  // 具体监听的网卡
        sockAddr.sin_port = htons(4196);    // 端口
        bind(serverSocket, (SOCKADDR *) &sockAddr, sizeof(SOCKADDR));
        if (listen(serverSocket, 10) == SOCKET_ERROR) {
            std::cout << "listen err" << std::endl;
            return 1;
        }
    }
    SOCKET clientSocket;
    acceptClient(&serverSocket, &clientSocket);
    sendMsgToClient(&clientSocket);
    closesocket(serverSocket);
    closesocket(clientSocket);
    WSACleanup();
    return 0;
}
void acceptClient(SOCKET *serverSocket, SOCKET *clientSocket) {
    sockaddr_in client_sin;
    int len = sizeof(client_sin);
    *clientSocket = accept(*serverSocket, (sockaddr *) &client_sin, &len);
    std::cout << "now client is coming" << std::endl;
}
void sendMsgToClient(SOCKET *clientSocket) {
    char a;
    for (int i = 0; i < 100; ++i) {
        for (int i = 0; i < 10; ++i) {
            a = i;
            send(*clientSocket, &a, sizeof a, 0);
        }}}

C++之发送HTTP请求

#################################
# CMakeLists.txt 文件内容如下
#################################
cmake_minimum_required(VERSION 3.25)
project(test)
set(CMAKE_CXX_STANDARD 14)
add_executable(test main.cpp)
# 注意此处的 wsock32(全名:libwsock32.a)该行命令相当于 g++ main.cpp -lwsock32.a 目的是链接 libwsock32.a 库
# 类似的还有 target_link_libraries(test2 pthread) 链接多线程并发动态库 g++ main.cpp -lpthread
target_link_libraries(test wsock32)

////////////////////////////////////
// main.cpp 文件源码如下
////////////////////////////////////
#include <winsock2.h>
#include <windows.h>
#include <iostream>
using std::cout;

int httpGet(const char *hostname);

int main() {
    httpGet("www.baidu.com");
    system("pause");
    return 0;
}

int httpGet(const char *hostname) {
//    const char *hostname = "www.baidu.com";
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        cout << "WSAStartup failed.n";
        system("pause");
        return 1;
    }
    SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    struct hostent *host;
    host = gethostbyname("www.baidu.com");
    SOCKADDR_IN SockAddr;
    SockAddr.sin_port = htons(80);
    SockAddr.sin_family = AF_INET;
    SockAddr.sin_addr.s_addr = *((unsigned long *) host->h_addr);
    cout << "Connecting...n";
    if (connect(Socket, (SOCKADDR *) (&SockAddr), sizeof(SockAddr)) != 0) {
        cout << "Could not connect";
        system("pause");
        return 1;
    }
    cout << "Connected.n";
    std::string url;
    url += url + "GET / HTTP/1.1rnHost: " + hostname + "rnConnection: closernrn";
    send(Socket, url.data(),
         strlen(url.data()), 0);
    char buffer[10000];
    int nDataLength;
    while ((nDataLength = recv(Socket, buffer, 10000, 0)) > 0) {
        int i = 0;
        while (buffer[i] >= 32 || buffer[i] == 'n' || buffer[i] == 'r') {
            cout << buffer[i];
            i += 1;
        }
    }
    closesocket(Socket);
    WSACleanup();
    return 0;
}

说明:

CSocket 在 WSock32.dll中实现,Socket API在ws2_32.dll实现

这两个DLL是两个不同层次的接口,调用关系如下:

网络应用程序(高级)----> CSocket(wsock32.dll) ----->Socket API(ws2_32.dll) -----> 网络传输服务进程(底层)

cpp-httplib实现http服务器与客户端

参考:https://blog.csdn.net/houxian1103/article/details/122350944

  • 使用到的开源库

cpp-httplib:https://github.com/yhirose/cpp-httplib
下载源码,将httplib.h头文件引入你自己的工程即可

jsoncpp:https://github.com/open-source-parsers/jsoncpp
下载源码,需要自行编译出动态库 libjsoncpp.dll,将这个动态库与include/json目录下的所有头文件拷贝至你自己的工程即可

rapidjson:https://github.com/Tencent/rapidjson
这也是一个json字符串处理的库,用起来比上面的要方便,只需要将工程源码下载下来,并将include/rapidjson目录下的所有头文件引入你自己的工程就可以使用了

  • 工程内容

image

  • CMakeLists.txt 文件内容
cmake_minimum_required(VERSION 3.23)
project(test)
set(CMAKE_CXX_STANDARD 14)

# 设置可执行文件输出目录
set(EXECUTABLE_OUTPUT_PATH build)

# 添加头文件的搜索路径
include_directories(include/http include/json)

# windows 平台下 CMakeLists.txt 文件中的路径分隔符最好全部使用反斜杠 /
# 添加库的搜索路径(注意:windows环境默认就有的库链接搜索路径是mingw64的安装目录中的lib文件夹并且这个文件夹不用在这里显示的指定)
link_directories(lib)
#link_directories(lib D:/C++/compiler/mylib D:/C++/compiler/x86_64-8.1.0-release-win32-seh-rt_v6-rev0/mingw64/opt/lib)

# 链接静态库(这个静态库完整的文件名称是 libws2_32.a )
#link_libraries(ws2_32 ssl crypto)       # ssl 与 crypto 库加了没鸡毛卵用,还是不能访问 https 地址
link_libraries(ws2_32)                 # 方式一:省略 lib 前缀与 .a 扩展名,能正确链接
#link_libraries(libws2_32.a)            # 方式二:完整写法,能正确链接
#link_libraries(ws2_32.a)               # 方式三:省略 lib 前缀,能正确链接
#link_libraries(libws2_32)              # 错误,省略 .a 扩展名导致 ld.exe 工具找不到目标库
#link_libraries(libjsoncpp.dll)         # 也可以用于链接动态库
# 添加加入编译的源文件
add_executable(test src/main.cpp)

# 动态链接库 libjsoncpp(是自己编译的,能找到是因为上方的目录中能找到这个库),注意:最终生成的可执行文件要想正确运行,必须要与动态库在同一个目录下才行
target_link_libraries(test libjsoncpp.dll)
#target_link_libraries(test libjsoncpp.dll)  # 方式一:完整写法
#target_link_libraries(test jsoncpp.dll)     # 方式二:省略 lib 前缀
#target_link_libraries(test libjsoncpp)      # 方式三:省略 .dll 后缀
#target_link_libraries(test jsoncpp)         # 方式四:前缀 lib 与后缀 .dll 均省略 (这种与静态库链接方式不同)
#target_link_libraries(test ws2_32)          # 也可以用于链接静态库

# 为了确保编译的可执行文件能正常运行,这里必须要将动态库安装(本质上相当于拷贝)到与可执行文件同一目录。(这种语法允许相对路径或绝对路径的文件完整全称且包含文件扩展名)
install(FILES
        lib/libjsoncpp.dll
        DESTINATION
        ${PROJECT_BINARY_DIR}/build)

源代码

#include <cstdio>
#include <iostream>
#include "json.h"
#include "httplib.h"

using httplib::Request;
using httplib::Response;
using httplib::Server;
using std::cout;
using std::endl;

void http_handle(const Request &req, Response &resp) {
    cout << req.method << endl;
    printf("func calledn");
    const char *lp = "<html><h2>hello world!</h2></html>";
    resp.set_content(lp, strlen(lp), "text/html");
}

void http_server() {
    Server http_svr;
    http_svr.Get("/get", http_handle);
    http_svr.Post("/post", [](const Request &req, Response &resp) {
        cout << req.body << endl;
        Json::Value resp_json;
        resp_json["login_status"] = true;
        Json::FastWriter w;
        resp.body = w.write(resp_json);
        resp.set_header("Content-Type", "application/json");
    });
    http_svr.set_mount_point("/", "./web");
    std::cout << "run 0.0.0.0:8080 ok" << std::endl;
    http_svr.listen("0.0.0.0", 8080);  // 阻塞在此处
}

void http_client(const std::string *protocol_ip, const std::string *path) {
    // HTTP
    httplib::Client cli(*protocol_ip);
    auto res = cli.Get(*path);
    res->status;
    res->body;
    std::cout << "===================================" << std::endl;
    std::cout << res << std::endl;
    std::cout << "===================================" << std::endl;
    std::cout << res->body << std::endl;
    std::cout << "===================================" << std::endl;
    std::cout << res->status << std::endl;
    std::cout << "===================================" << std::endl;
    std::cout << res->content_length_ << std::endl;
}


int main(int argc, char *argv[]) {
    http_server();
//    std::string addr = "http://dimio.altervista.org";
//    std::string path = "/ita/index.html";
//    http_client(&addr, &path);

    // 额.......不明白为啥一直不支持SSL
//    std::string addr = "https://www.baidu.com";
//    std::string path = "/";
//    http_client(&addr, &path);
    std::cout << "ok" << std::endl;
    return 0;
}

C++ easyloggingpp 日志库的简单使用

easyloggingpp地址:https://github.com/amrayn/easyloggingpp

0.工程结构如下图
image

1.下载源代码并将easylogging++.cceasylogging++.h 复制到你自己的工程

2.创建一个配置文件log.config

* GLOBAL:
   FORMAT               =  "[ %level ] %datetime{%Y-%M-%d %H:%m:%s} %loc >>>>>>>>> %msg"
   FILENAME             =  "D:/tmp_code/test/my.log"
   ENABLED              =  true
   TO_FILE              =  true
   TO_STANDARD_OUTPUT   =  true
   SUBSECOND_PRECISION  =  6
   PERFORMANCE_TRACKING =  true
   MAX_LOG_FILE_SIZE    =  2097152 ## 2MB - Comment starts with two hashes (##)
   LOG_FLUSH_THRESHOLD  =  100 ## Flush after every 100 logs
 * DEBUG:
   FORMAT               = "[ %level ] %datetime{%Y-%M-%d %H:%m:%s} %loc >>>>>>>>> %msg"

3.代码

************************
* CMakeLists.txt
************************
cmake_minimum_required(VERSION 3.25)
project(test)
set(CMAKE_CXX_STANDARD 14)
add_executable(test main.cpp easylogging++.cc)

************************
* main.cpp
************************
#include "easylogging++.h"
INITIALIZE_EASYLOGGINGPP
void configLog() {
    el::Configurations conf("D:/tmp_code/test/log.conf");
    el::Loggers::reconfigureLogger("default", conf);
    el::Loggers::reconfigureAllLoggers(conf);
}
int main(int argc, char *argv[]) {
    configLog();
    LOG(INFO) << "My first info log using default logger";
    return 0;
}

使用spdlog

地址:https://github.com/gabime/spdlog
步骤:
1、下载源码
2、拷贝源码中的include文件夹到你自己的工程中
3、引入 #include <spdlog/spdlog.h> 头文件声明
4、使用
image

使用culr库发送https/http请求

1、下载curl动态库文件:https://curl.se/windows/
2、拷贝curl压缩包中的include目录到你的工程中
3、拷贝curl压缩包中的bin目录中的动态链接库libcurl-x64.dll到你的工程中
4、工程结构如下
image

【main.cpp】

#include <iostream>
#include <curl/curl.h>
#include <string>

size_t write_callback(char *ptr, size_t size, size_t nmemb, std::string *userdata) {
    userdata->append(ptr, size * nmemb);
    return size * nmemb;
}

std::string perform_request(const std::string &url, const std::string &method, const std::string &data) {
    CURL *curl = curl_easy_init();
    std::string response;
    if (curl) {
        // 关闭curl的证书验证,才能发起https请求,不建议在生产环境使用
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
        curl_easy_perform(curl);
        curl_easy_cleanup(curl);
    }
    return response;
}

int main(int argc, char *argv[]) {
    std::string url = "https://www.baidu.com";
    std::string url1 = "http://www.baidu.com";
    std::string method = "GET";
    std::string data = "";
    std::string response = perform_request(url, method, data);
    std::cout << response << std::endl;
    return 0;
}

参考博客

windows C++学习之Socket

windows C++ 发送HTTP请求

C++静态库与动态库

g++编译参数---CMake详细使用教程

原文链接: https://www.cnblogs.com/hhddd-1024/p/17084228.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    C++之Socket简单使用

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/315210

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月16日 下午1:40
下一篇 2023年2月16日 下午1:40

相关推荐