热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c在多线程的boostasio中随机EOF

我对提升asio相当陌生,并且在多线程服务器中遇到随机文件结尾.我可以在这个小例子中重现我的问题:服务器:这是一个简单的回显服务器.该协议很简单:(1)客户端连接(2)服务器读

我对提升asio相当陌生,并且在多线程服务器中遇到随机文件结尾.

我可以在这个小例子中重现我的问题:

服务器:

这是一个简单的回显服务器.该协议很简单:

>(1)客户端连接
>(2)服务器读取一个字节.该字节是要读取和发送回的字符串的长度.
>(3)服务器读取N个字节.
>(4)服务器将N 1个字节发送回客户端,然后返回(2).

当客户端断开连接时,在(3)中捕获到一个EOF,并且处理程序循环停止.

class MySocket{
public:
char buffer[257];
boost::asio::ip::tcp::socket socket;
MySocket(boost::asio::io_service*ios):socket(*ios){}
~MySocket(){}
};
//Handlers
void readN(std::shared_ptrserver,const boost::system::error_code&ec);
//(4)
void echo(std::shared_ptrserver,const boost::system::error_code&ec){
if(ec){
throw std::exception(("This is NOT OK: "+ec.message()).c_str());}
size_t n=server->buffer[0]&0xFF;
std::cout<buffer+1,n)< boost::asio::async_write(server->socket,boost::asio::buffer(server->buffer,n+1),boost::bind(readN,server,boost::asio::placeholders::error));}
//(3)
void read(std::shared_ptrserver,const boost::system::error_code&ec){
if(ec){
throw std::exception(("This is OK: "+ec.message()).c_str());}
size_t n=server->buffer[0]&0xFF;
boost::asio::async_read(server->socket,boost::asio::buffer(server->buffer+1,n),boost::bind(echo,server,boost::asio::placeholders::error));}
//(2)
void readN(std::shared_ptrserver,const boost::system::error_code&ec){
if(ec){
throw std::exception(("This is also NOT OK: "+ec.message()).c_str());}
boost::asio::async_read(server->socket,boost::asio::buffer(server->buffer+0,1),boost::bind(read,server,boost::asio::placeholders::error));}
//Server
void serve(boost::asio::io_service*ios){
for(;;){
try{ios->run();break;}
catch(const std::exception&e){std::cout<//(1)
void accept(boost::asio::io_service*ios,boost::asio::ip::tcp::acceptor*acceptor,std::shared_ptrserver,const boost::system::error_code&ec){
if(server.get()!=nullptr){
server->socket.set_option(boost::asio::ip::tcp::no_delay(true));
readN(server,ec);}
server.reset(new MySocket(ios));
acceptor->async_accept(server->socket,boost::bind(accept,ios,acceptor,server,boost::asio::placeholders::error));}
int main(){
boost::asio::io_service ios;
boost::asio::ip::tcp::acceptor acceptor(ios,boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),1207));
boost::asio::io_service::work work(ios);
accept(&ios,&acceptor,nullptr,boost::system::error_code());
// std::thread other(boost::bind(serve,&ios));
serve(&ios);
acceptor.close();
ios.stop();
// other.join();
return 0;}

客户:

客户端一次连接到服务器并发送1000个字符串.

int main(){
try{
boost::asio::io_service ios;
boost::asio::ip::tcp::socket socket(ios);
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string("127.0.0.1"),1207);
socket.connect(endpoint);
socket.set_option(boost::asio::ip::tcp::no_delay(true));
char buf[257];
for(size_t i=0;i<1000;++i){
size_t n=(i%127)+1;
buf[0]=(char)n;
for(size_t j=0;j buf[j+1]=(char)('A'+(j+i)%26);}
socket.send(boost::asio::buffer(buf,n+1));
socket.receive(boost::asio::buffer(buf,1));
if((buf[0]&0xFF)!=n){
throw std::exception("Oups!");}
socket.receive(boost::asio::buffer(buf+1,n));
for(size_t j=0;j if(buf[j+1]!=(char)('A'+(j+i)%26)){
throw std::exception("Oups!");}}
std::cout< catch(const std::exception&e){
std::cout< return 0;}

当服务器仅使用一个线程(对其他线程进行注释)时,服务器正确地回显1000个字符串.

当服务器使用其他线程时,在随机数量的打印字符串之后,在(4)中捕获EOF.这永远都不会发生.

>我尝试用绞线包装所有异步调用,但是没有用.
>据我所知,没有数据争用问题.处理程序应一个接一个地调用.

我错过了什么 ?

处理多线程asio应用程序的正确习惯是什么?

编辑:

我做了一些测试,看来如果我替换了这一行

throw std::exception(("This is NOT OK: "+ec.message()).c_str());

有:

std::cout<<"This is not OK: "<

即使我看到几次错误地将几个EOF错误地传递为参数,服务器也正确地回响了1000行.

所以我想问题是为什么当套接字显然没有关闭时,为什么会得到错误的boost :: asio :: error :: eof?

这不是说here.

解决方法:

这是boost :: asio 1.54.0的错误

我在互联网上发现了两个类似的线程:

> this one.
>和that one(堆栈溢出).

还有一个错误报告here.

我安装了boost 1.53,现在可以正常工作了.


推荐阅读
author-avatar
手机用户2502937257
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有