文章目录
以下是本篇文章正文内容
一、同步写
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