【Asio网络编程】socket同步读写


以下是本篇文章正文内容

一、同步写

boost::asio提供了几种同步写的api:

  • write_some可以每次向指定的空间写入固定的字节数,如果写缓冲区满了,就只写一部分,返回写入的字节数。
  • send函数会一次性将buffer中的内容发送给对端,如果有部分字节因为发送缓冲区满无法发送,则阻塞等待,直到发送缓冲区可用,则继续发送完成。
  • write函数,可以一次性将所有数据发送给对端,如果发送缓冲区满了则阻塞,直到发送缓冲区可用,将数据发送完成。

1.1 write_some

write_some可以每次向指定的空间写入固定的字节数,如果写缓冲区满了,就只写一部分,返回写入的字节数。

void  wirte_to_socket(asio::ip::tcp::socket& sock) {
   
   
    std::string buf = "Hello World!";
    std::size_t  total_bytes_written = 0;
    //循环发送
    //write_some会返回每次写入的字节数
    //total_bytes_written是已经发送的字节数。
    //每次发送buf.length()- total_bytes_written)字节数据
    while (total_bytes_written != buf.length()) {
   
   
        // write_some(),第一个参数是地址,第二个参数是长度
        total_bytes_written += sock.write_some(asio::buffer(buf.c_str() + total_bytes_written,
                                               buf.length() - total_bytes_written));
    }
}

1.2 send

write_some使用起来比较麻烦,需要多次调用,asio提供了send函数。send函数会一次性将buffer中的内容发送给对端,如果有部分字节因为发送缓冲区满无法发送,则阻塞等待,直到发送缓冲区可用,则继续发送完成。

int send_data_by_send() {
   
   
    std::string raw_ip_address = "127.0.0.1";
    unsigned short port_num = 3333;
    try {
   
   
        asio::ip::tcp::endpoint
            ep(asio::ip::address::from_string(raw_ip_address),
                port_num);
        asio::io_service ios;
        // Step 1. Allocating and opening the socket.
        asio::ip::tcp::socket sock(ios, ep.protocol());
        sock.connect(ep);
        std::string buf = "Hello World!";

        /*
        三种返回值:
            1 小于0,出现socket系统级错误
            2 大于0,是buffer的长度,即如果发送不完则一直阻塞等待
            3 等于0,对端关闭
        */ 
        int send_length = sock.send(asio::buffer(buf.c_str(), buf.length()));
        if (send_length <= 0) {
   
   
            std::cout << "send failed" << std::endl;
            return 0;
        }
    }
    catch (system::system_error& e) {
   
   
        std::cout << "Error occured! Error code = " << e.code()
            << ". Message: " << e.what();
        return e.code().value();
    }
    return 0;
}

1.3 write

类似send方法,asio还提供了一个write函数,可以一次性将所有数据发送给对端,如果发送缓冲区满了则阻塞,直到发送缓冲区可用,将数据发送完成。

在这里插入代码片

二、 同步读

  • read_some
  • receive
  • read

2.1 read_some

读取指定字节数的接口read_some, 数据在不超过指定的长度的时候有多少读多少,读完直接向后运行,没有数据则会一直等待。
所以一般情况下:我们读取数据都需要采用循环读的方式读取数据,因为一次read_some 完毕不能保证读到我们需要长度的数据,read 完一次需要判断读到的数据长度再决定是否还需要再次读取。

代码逻辑:

std::string read_from_socket(asio::ip::tcp::socket& sock) {
   
   
    const unsigned char MESSAGE_SIZE = 7;
    char buf[MESSAGE_SIZE];
    std::size_t total_bytes_read = 0;
    while (total_bytes_read != MESSAGE_SIZE) {
   
   
    	// 和write_some类似,返回读取字节的长度,如果读不完则循环下次接着读
        total_bytes_read += sock.read_some(asio::buffer(buf + total_bytes_read,
                							MESSAGE_SIZE 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值