侧边栏壁纸
博主头像
李振洋的博客博主等级

歌颂动荡的青春

  • 累计撰写 38 篇文章
  • 累计创建 6 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

C++ 网络编程-asio

C++ 网络编程-asio

网络编程基本流程

服务端

1)socket——创建socket对象。

2)bind——绑定本机ip+port。

3)listen——监听,若监听到连接,则建立起连接。

4)accept——再创建一个socket对象给客户端收发消息。在现实中服务端面对多个客户端,为了区分各个客户端,则需要为每个客户端都再分配一个socket对象进行收发消息。

5)read、write——收发消息。

客户端

1)socket——创建socket对象。

2)connect——根据服务端ip+port,发起连接请求。

3)write、read——建立连接后,就可发收消息了。

编译Boost库

Boost库是为C++语言标准库提供扩展的一些C++程序库的总称,由Boost社区组织开发、维护。

  1. 获取Boost源码 Boost Downloads

  2. 在源码文件夹的根目录下有bootstrap.bat文件,双击运行会生成b2.exe

  3. 启动power shell,在根目录执行 “.\b2.exe toolset=msvc”进行编译

  4. 编译过后,会在stage文件夹下生成lib文件夹,里面就是Boost的lib库

为VisualStudio配置Boost库

  1. 用VisualStudio 创建一个C++控制台应用工程,然后右键工程选择属性

  2. 选择VC++目录 -> 在包含目录,添加Boost源码路径;

  3. 选择VC++目录 -> 库目录,添加Boost源码路径下的stage\lib;

网络编程-同步读写

同步读写指的是在调用read或write等I/O操作时,当前线程会阻塞,直到操作完成(即读取到数据或数据被成功发送)。也就是说,在执行读写操作的期间,程序无法进行其他任务,必须等待I/O操作完成后才能继续执行下一步。

当网络延迟较高或需要频繁进行I/O操作时,线程会大量时间处于等待状态,导致CPU资源浪费,降低了系统整体的吞吐量。对于高并发场景,使用同步I/O可能需要大量线程来处理多个连接,这会导致线程切换开销大,系统资源消耗严重。

同步读写-客户端设计

根据服务器对端的ip和端口创建一个endpoint,然后创建socket连接这个endpoint,之后就可以用同步读写的方式发送和接收数据

#include <iostream>
#include <boost/asio.hpp>
using namespace std;
using namespace boost::asio::ip;
const int MAX_LENGTH = 1024;
int main()
{
    try {
        //创建上下文服务
        boost::asio::io_context   ioc;
        //构造endpoint
        tcp::endpoint  remote_ep(address::from_string("127.0.0.1"), 10086);
        tcp::socket  sock(ioc);
        boost::system::error_code   error = boost::asio::error::host_not_found; ;
        sock.connect(remote_ep, error);
        if (error) {
            cout << "connect failed, code is " << error.value() << " error msg is " << error.message();
            return 0;
        }
        std::cout << "Enter message: ";
        char request[MAX_LENGTH];
        std::cin.getline(request, MAX_LENGTH);
        size_t request_length = strlen(request);
        boost::asio::write(sock, boost::asio::buffer(request, request_length));
        char reply[MAX_LENGTH];
        size_t reply_length = boost::asio::read(sock,
            boost::asio::buffer(reply, request_length));
        std::cout << "Reply is: ";
        std::cout.write(reply, reply_length);
        std::cout << "\n";
    }
    catch (std::exception& e) {
        std::cerr << "Exception: " << e.what() << endl;
    }
    return 0;
}

同步读写-服务器端设计

#include <iostream>
#include <cstdlib>
#include <iostream>
#include <boost/asio.hpp>
#include <set>
using boost::asio::ip::tcp;
const int max_length = 1024;
typedef std::shared_ptr<tcp::socket> socket_ptr;
std::set<std::shared_ptr<std::thread>>  thread_set;
using namespace std;
/*

session函数
为服务器处理客户端请求,每当获取客户端连接后就调用该函数。
在session函数里里进行应答式的读写

*/
void session(socket_ptr sock) {
    try {
        for (;;) {
            char data[max_length];
            memset(data, '\0', max_length);
            boost::system::error_code error;
            size_t length = sock->read_some(boost::asio::buffer(data, max_length), error);
            if (error == boost::asio::error::eof) {
                std::cout << "connection closed by peer" << endl;
                break;
            }
            else if (error) {
                throw boost::system::system_error(error);
            }
            cout << "receive from " << sock->remote_endpoint().address().to_string() << endl;
            cout << "receive message is " << data << endl;
            //回传信息值
            boost::asio::write(*sock, boost::asio::buffer(data, length));
        }
    }
    catch (std::exception& e) {
        std::cerr << "Exception in thread: " << e.what() << "\n" << std::endl;
    }
}

/*
server
根据服务器ip和端口创建服务器acceptor用来接收数据
用socket接收新的连接,为socket创建session。
创建线程调用session函数可以分配独立的线程用于socket的读写,保证acceptor不会因为socket的读写而阻塞
*/
void server(boost::asio::io_context& io_context, unsigned short port) {
    tcp::acceptor a(io_context, tcp::endpoint(tcp::v4(), port));
    for (;;) {
        socket_ptr socket(new tcp::socket(io_context));
        a.accept(*socket);
        auto t = std::make_shared<std::thread>(session, socket);
        thread_set.insert(t);
    }
}

int main()
{
    try {
        boost::asio::io_context  ioc;
        server(ioc, 10086);
        for (auto& t : thread_set) {
            t->join();
        }
    }
    catch (std::exception& e) {
        std::cerr << "Exception " << e.what() << "\n";
    }
    return 0;
}

0

评论区