void Session::handle_read(const boost::system::error_code& error, size_t bytes_transferred, std::shared_ptr<Session> shared_self) {
if (!error) {
int copy_len = 0;
while (bytes_transferred > 0) {
if (!_b_head_parse) {
if (bytes_transferred + _recv_head_node->_cur_len < HEAD_LENGTH) {
memcpy(_recv_head_node->_data + _recv_head_node->_cur_len, _data + copy_len, bytes_transferred);
_recv_head_node->_cur_len += bytes_transferred;
memset(_data, 0, MAX_LENGTH);
_socket.async_read_some(boost::asio::buffer(_data, MAX_LENGTH), std::bind(&Session::handle_read, this, std::placeholders::_1, std::placeholders::_2, shared_self));
return;
}
int head_remain = HEAD_LENGTH - _recv_head_node->_cur_len;
memcpy(_recv_head_node->_data + _recv_head_node->_cur_len, _data + copy_len, head_remain);
copy_len += head_remain;
bytes_transferred -= head_remain;
short data_len = 0;
memcpy(&data_len, _recv_head_node->_data, HEAD_LENGTH);
cout << "data_len is " << data_len << endl;
if (data_len > MAX_LENGTH) {
std::cout << "invalid data length is " << data_len << endl;
_server->ClearSession(_uuid);
return;
}
_recv_msg_node = make_shared<MsgNode>(data_len);
if (bytes_transferred < data_len) {
memcpy(_recv_msg_node->_data + _recv_msg_node->_cur_len, _data + copy_len, bytes_transferred);
_recv_msg_node->_cur_len += bytes_transferred;
::memset(_data, 0, MAX_LENGTH);
_socket.async_read_some(boost::asio::buffer(_data, MAX_LENGTH), std::bind(&Session::handle_read, this, std::placeholders::_1, std::placeholders::_2, shared_self));
_b_head_parse = true;
return;
}
memcpy(_recv_msg_node->_data + _recv_msg_node->_cur_len, _data + copy_len, data_len);
_recv_msg_node->_cur_len += data_len;
copy_len += data_len;
bytes_transferred -= data_len;
_recv_msg_node->_data[_recv_msg_node->_total_len] = '\0';
cout << "receive data is " << _recv_msg_node->_data << endl;
Send(_recv_msg_node->_data, _recv_msg_node->_total_len);
_b_head_parse = false;
_recv_head_node->clear();
if (bytes_transferred <= 0) {
::memset(_data, 0, MAX_LENGTH);
_socket.async_read_some(boost::asio::buffer(_data, MAX_LENGTH), std::bind(&Session::handle_read, this, std::placeholders::_1, std::placeholders::_2, shared_self));
return;
}
continue;
} else {
int remain_msg = _recv_msg_node->_total_len - _recv_msg_node->_cur_len;
if (bytes_transferred < remain_msg) {
memcpy(_recv_msg_node->_data + _recv_msg_node->_cur_len, _data + copy_len, bytes_transferred);
_recv_msg_node->_cur_len += bytes_transferred;
::memset(_data, 0, MAX_LENGTH);
_socket.async_read_some(boost::asio::buffer(_data, MAX_LENGTH), std::bind(&Session::handle_read, this, std::placeholders::_1, std::placeholders::_2, shared_self));
return;
}
memcpy(_recv_msg_node->_data + _recv_msg_node->_cur_len, _data + copy_len, remain_msg);
_recv_msg_node->_cur_len += remain_msg;
bytes_transferred -= remain_msg;
copy_len += remain_msg;
_recv_msg_node->_data[_recv_msg_node->_total_len] = '\0';
cout << "receive data is " << _recv_msg_node->_data << endl;
Send(_recv_msg_node->_data, _recv_msg_node->_total_len);
_b_head_parse = false;
_recv_head_node->clear();
if (bytes_transferred <= 0) {
::memset(_data, 0, MAX_LENGTH);
_socket.async_read_some(boost::asio::buffer(_data, MAX_LENGTH), std::bind(&Session::handle_read, this, std::placeholders::_1, std::placeholders::_2, shared_self));
return;
}
continue;
}
}
} else {
std::cout << "handle read failed, error is " << error.what() << endl;
close();
_server->ClearSession(_uuid);
}
}
int main() {
try {
boost::asio::io_context ioc;
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;
}
thread send_thread([&sock] {
for (;;) {
this_thread::sleep_for(std::chrono::milliseconds(2));
const char* request = "hello world!";
size_t request_length = strlen(request);
char send_data[MAX_LENGTH] = {0};
memcpy(send_data, &request_length, 2);
memcpy(send_data + 2, request, request_length);
boost::asio::write(sock, boost::asio::buffer(send_data, request_length + 2));
}
});
thread recv_thread([&sock] {
for (;;) {
this_thread::sleep_for(std::chrono::milliseconds(2));
cout << "begin to receive..." << endl;
char reply_head[HEAD_LENGTH];
size_t reply_length = boost::asio::read(sock, boost::asio::buffer(reply_head, HEAD_LENGTH));
short msglen = 0;
memcpy(&msglen, reply_head, HEAD_LENGTH);
char msg[MAX_LENGTH] = {0};
size_t msg_length = boost::asio::read(sock, boost::asio::buffer(msg, msglen));
std::cout << "Reply is: ";
std::cout.write(msg, msglen) << endl;
std::cout << "Reply len is " << msglen;
std::cout << "\n";
}
});
send_thread.join();
recv_thread.join();
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << endl;
}
return 0;
}