C++ 如何确保客户端首先使用boost asio关闭套接字
服务器从客户端读取10个字节,然后写回10个字节,代码如下: 服务器:C++ 如何确保客户端首先使用boost asio关闭套接字,c++,boost-asio,C++,Boost Asio,服务器从客户端读取10个字节,然后写回10个字节,代码如下: 服务器: #include <iostream> using namespace std; #include <boost/thread/thread.hpp> #include <boost/asio.hpp> #include <boost/asio/spawn.hpp> using namespace boost; using namespace boost::asio; usi
#include <iostream>
using namespace std;
#include <boost/thread/thread.hpp>
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
using namespace boost;
using namespace boost::asio;
using namespace boost::asio::ip;
namespace ba=boost::asio;
#define SERVER_PORT 12345
#define DATA_LEN 10
struct session : public std::enable_shared_from_this<session>
{
tcp::socket socket_;
boost::asio::steady_timer timer_;
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
explicit session(boost::asio::io_context& io_context, tcp::socket socket)
: socket_(std::move(socket)),
timer_(io_context),
strand_(io_context.get_executor())
{ }
void go()
{
auto self(shared_from_this());
boost::asio::spawn(strand_, [this, self](boost::asio::yield_context yield)
{
spawn(yield, [this, self](ba::yield_context yield) {
timer_.expires_from_now(10s); // 10 second
while (socket_.is_open()) {
boost::system::error_code ec;
timer_.async_wait(yield[ec]);
// timeout triggered, timer was not canceled
if (ba::error::operation_aborted != ec) {
socket_.close();
}
}
});
try
{
// read 10 bytes
string packet;
boost::system::error_code ec;
ba::async_read(socket_,
ba::dynamic_buffer(packet),
ba::transfer_exactly(DATA_LEN),
yield[ec]);
// write 10 bytes
static string pkt(10, 'a');
boost::system::error_code ecw;
boost::asio::write(socket_, boost::asio::buffer(pkt), ecw);
}
catch (...)
{
cout << "exception" << endl;
}
// Sleep(1000); // any better way than Sleep?
timer_.cancel();
socket_.close();
});
}
};
int main() {
ba::io_context io_context;
auto worker = ba::make_work_guard(io_context);
std::thread([&]()
{
tcp::acceptor acceptor(io_context,
tcp::endpoint(tcp::v4(), SERVER_PORT));
for (;;)
{
boost::system::error_code ec;
tcp::socket socket(io_context);
acceptor.accept(socket, ec);
if (!ec) {
std::make_shared<session>(io_context, std::move(socket))->go();
}
}
}).detach();
io_context.run();
}
#包括
使用名称空间std;
#包括
#包括
#包括
使用名称空间boost;
使用名称空间boost::asio;
使用名称空间boost::asio::ip;
名称空间ba=boost::asio;
#定义服务器端口12345
#定义数据\u LEN 10
结构会话:public std::从\u中启用\u共享\u
{
tcp::socket-socket;
升压::asio::稳定定时器;
boost::asio::串;
显式会话(boost::asio::io_上下文&io_上下文,tcp::socket)
:套接字(标准::移动(套接字)),
计时器(io上下文),
串(io_上下文。get_executor())
{ }
void go()
{
自动自我(从_this()共享_);
boost::asio::spawn(strand_u,[this,self](boost::asio::yield_上下文yield)
{
繁殖(产量[这个,自我](ba::产量\上下文产量){
计时器从现在开始(10秒);//10秒
while(套接字打开(){
boost::system::error_code ec;
定时器异步等待(收益率[ec]);
//超时已触发,计时器未取消
if(ba::error::operation_aborted!=ec){
插座关闭();
}
}
});
尝试
{
//读取10字节
字符串包;
boost::system::error_code ec;
ba::异步读取(套接字读取,
ba::动态缓冲区(数据包),
ba::准确传输(数据长度),
产量[ec];
//写入10个字节
静态字符串pkt(10,'a');
boost::system::错误代码ecw;
boost::asio::write(套接字、boost::asio::buffer(pkt)、ecw);
}
捕获(…)
{
为什么不简单地保持套接字打开直到远程端关闭它呢?当远程端关闭套接字时,你的端将变得可读,“读取”操作将返回零字节读取。添加boost版本,编译器。无法使用gcc编译代码(Ubuntu 7.4.0-1ubuntu1~18.04.1)7.4.0
和boost-1.65.1
@Someprogrammerdude,谢谢。我在(1){async_read(100_字节)}
完成实际作业后,在出现异常之前,关闭套接字,似乎可以正常工作:)为什么不简单地保持套接字打开,直到远程端关闭它?当远程端关闭套接字时,您的端将变得可读,并且“读取”操作将返回零字节读取。添加boost版本,编译器。无法使用gcc编译代码(Ubuntu 7.4.0-1ubuntu1~18.04.1)7.4.0
和boost-1.65.1
@Someprogrammerdude,谢谢。我在(1){async_read(100_字节)}完成实际作业后,在出现异常之前,关闭套接字,似乎可以正常工作:)
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
using namespace std;
using boost::asio::ip::tcp;
namespace ba=boost::asio;
#define SERVER "11.22.33.44" // replace with your external ip address
#define PORT "12345"
static string pkt = "1234567890"; // 10 bytes
int main() {
boost::asio::io_context io_context;
while(1) {
getchar();
try {
tcp::socket s(io_context);
tcp::resolver resolver(io_context);
boost::asio::connect(s, resolver.resolve(SERVER, PORT));
// write 10 bytes
boost::system::error_code ecw;
ba::write(s, ba::buffer(pkt), ecw);
// read 10 bytes
string packet;
boost::system::error_code ec;
ba::read(s,
ba::dynamic_buffer(packet),
ba::transfer_exactly(10),
ec);
// client close socket first
{
boost::system::error_code ec;
s.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
s.close();
}
} catch (...) {
cout << "exception" << endl;
}
cout << "done" << endl;
}
return 0;
}