- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 ASIO
开发网络应用程序并提到了Chat-Server/Client
我问过类似的问题Here
为了更好地解释,我在这里添加了更多代码:
我的 Cserver Class
class CServer {
private:
mutable tcp::acceptor acceptor_; // only in the listener
asio::io_service& io_;
CSerSessionsManager mng_;
std::string ip_;
std::string port_;
public:
CServer::CServer(asio::io_service& io_service, const std::string IP, const std::string port) : io_(io_service), acceptor_(io_service)
, ip_(IP), port_(port)
{
DEBUG_MSG("Listener Created");
}
~CServer()
{
DEBUG_MSG("Listener Destroyed");
acceptor_.close();
}
void initProtocol()
{
DEBUG_MSG(" Protocol Initiated");
std::array<unsigned char, 4> ip;
std::string delimiter = ".";
//Parse the IP String
size_t pos = 0;
auto i = 0;
std::string token;
while ((pos = ip_.find(delimiter)) != std::string::npos) {
token = ip_.substr(0, pos);
ip[i] = std::stoi(token);//what if stoi fails
i++;
ip_.erase(0, pos + delimiter.length());
}
ip[i] = std::stoi(ip_);
asio::ip::address_v4 address(ip);
tcp::endpoint ep(address, std::stoi(port_));
static std::mutex m;
std::unique_lock<std::mutex> lck(m, std::defer_lock);
//Critical Section start
lck.lock();
acceptor_ = tcp::acceptor(io_, ep);//Creating IOService
lck.unlock();
//Critical Section End
listen();
}
void listen()
{
DEBUG_MSG("!==============================================================!");
////Critical Section
static std::mutex m;
std::lock_guard<std::mutex> lock(m);
sessionPtr newSession = std::make_shared<CSerSession>(io_, mng_);
try
{
acceptor_.async_accept(newSession->socket(), std::bind(&CServer::handle_accept, /*shared_from_this()*/ this, newSession,
std::placeholders::_1));
///*asio::error_code ec;
//pSocket_->shutdown(asio::ip::tcp::socket::shutdown_send, ec);*/
}
catch (const std::bad_weak_ptr& e)
{
DEBUG_MSG(e.what());
throw e;
}
DEBUG_MSG("Listen Activated");
}
void handle_accept(sessionPtr newSession, const asio::error_code& error)
{
if (!acceptor_.is_open())
{
return;
}
if (!error)
{
DEBUG_MSG("Incoming Session accepted");
//Do I need a Lock here?
//Critical Section
static std::mutex m;
std::lock_guard<std::mutex> lock(m);
newSession->startSession();
listen();
}
else
{
DEBUG_MSG("Listen_Error");
// //throw ASIOError(Listen_Error);
DEBUG_MSG(error.message());
return;
}
}
};
我的 CSerSessionsManager Class
class CSerSessionsManager{
private:
std::set<sessionPtr> sessions_; //Active Sessions : Online Info
public:
CSerSessionsManager();
~CSerSessionsManager();
void addSession(sessionPtr session);
void dropSession(sessionPtr session);
};
CSerSessionsManager::CSerSessionsManager()
{
DEBUG_MSG("Construction");
}
CSerSessionsManager::~CSerSessionsManager()
{
DEBUG_MSG("Destruction");
}
void CSerSessionsManager::addSession(sessionPtr session)
{
DEBUG_MSG("Incoming Session Entry saved");
//Critical Section
static std::mutex m;
std::lock_guard<std::mutex> lock(m);
sessions_.insert(session);
}
void CSerSessionsManager::dropSession(sessionPtr session)
{
//Properly handle Existing connections first shutdown sockets
DEBUG_MSG("Session dropped");
//Critical Section
static std::mutex m;
std::lock_guard<std::mutex> lock(m);
std::set<sessionPtr>::iterator it;
for (it = sessions_.begin(); it != sessions_.end(); ++it)
{
if ((*it) == session)
{
sessions_.erase(session);
return;
}
}
//throw ASIOError(Session_Not_Found);
}
还有我的CSerSession Class
class CSerSession : public std::enable_shared_from_this < CSerSession > {
private:
mutable tcp::socket socket_; // client connection
CSerSessionsManager& manager_;
std::string ip_;
std::string port_;
CBuffer msg_;
public:
CSerSession(asio::io_service& io_service, CSerSessionsManager& mng) :
manager_(mng), socket_(io_service)
{
DEBUG_MSG("Server Session Created");
}
~CSerSession()
{
DEBUG_MSG("Server Session Destroyed");
}
void startSession()
{
DEBUG_MSG("Server Session Started");
//Critical Section
static std::mutex m;
std::lock_guard<std::mutex> lock(m);
manager_.addSession(shared_from_this());//Multiple threads should not try adding section
read(msg_);
}
void handle_read(const asio::error_code& error /*error*/, size_t bytes_transferred /*bytes_transferred*/)
{
if (!error)
{
DEBUG_MSG("Read");
//Critical Section
static std::mutex m;
std::lock_guard<std::mutex> lock(m);
read(msg_);
}
else
{
DEBUG_MSG("Read Error Detected : " << error.message());
//Check If shared_from_this() is valid or not
try
{
//Check if session was already dropped e.g. server object destroying
//i.e. if session object exists
DEBUG_MSG("Dropping Session");
//if (error == asio::error::operation_aborted)
manager_.dropSession(shared_from_this());
}
catch (const std::bad_weak_ptr& e)
{
DEBUG_MSG(e.what());
throw e;
}
return;
}
}
void read(CBuffer & buff)
{
DEBUG_MSG("Read");
asio::async_read(socket_, asio::buffer(const_cast<char *> (buff.getReceived()), buff.buffsize),
std::bind(&CSerSession::handle_read, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
}
tcp::socket& socket()
{
//Critical Section
static std::mutex m;
std::lock_guard<std::mutex> lock(m);
return socket_;
}
};
我创建了 CServer Object
主要如下:
void main()
{
try
{
asio::io_service io_service;
//CServer server(io_service, "Default", "127.0.0.1", "8000");
auto sPtr = std::make_shared<CServer>(io_service, "127.0.0.1", "8000");
sPtr->initProtocol();
//server.initProtocol();
asio::thread t(boost::bind(&asio::io_service::run, &io_service));
}
catch (...)
{
}
system("Pause");
}
我得到的输出日志如下:
CSerSessionsManager::CSerSessionsManager : 183 : Construction
CServer::CServer : 239 : Listener Created
CServer::initProtocol : 250 : Protocol Initiated
CServer::listen : 288 : !==============================================================!
CSerSession::CSerSession : 108 : Server Session Created
CServer::listen : 309 : Listen Activated
CServer::~CServer : 244 : Listener Destroyed
CSerSessionsManager::~CSerSessionsManager : 188 : Destruction
CSerSession::~CSerSession : 113 : Server Session Destroyed
当 CServer Object
破坏相关CSerSession Object
也破坏, 所以从 ~CSerSession()
返回时它抛出异常 boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::system_error> > at memory location 0x0277F19C.
在下面的代码行中:
#ifndef BOOST_EXCEPTION_DISABLE
throw enable_current_exception(enable_error_info(e));
#else
throw e;
#endif
}
我尝试了很多调试并尝试使用 signal mechanism
也如 HTTP Server 中所讨论,但我被困在这里,无法继续。
完整的代码可以在这里查看: MyCode
如何解决?
最佳答案
来自链接代码的固定版本:Live On Coliru我明白了
CSerSessionsManager : 184 : Construction
CServer : 240 : Listener Created
initProtocol : 251 : Protocol Initiated
~CServer : 245 : Listener Destroyed
~CSerSessionsManager : 189 : Destruction
NOTE: this was because I already had something listening on port 8000 (yay for error reporting!)
字段的初始化顺序修复了吗?或者我的系统上有什么东西根本没有运行(因为我更快的机器上的竞争条件?)。
看起来像后者,因为我得到了 Coliru
CSerSessionsManager : 184 : Construction
CServer : 240 : Listener Created
initProtocol : 251 : Protocol Initiated
listen : 289 : !===================================!
CSerSession : 109 : Server Session Created
listen : 310 : Listen Activated
~CServer : 245 : Listener Destroyed
~CSerSessionsManager : 189 : Destruction
~CSerSession : 114 : Server Session Destroyed
那么,让我们仔细看看:
为什么要解析 IP 字符串?这就是 address_v4
的用途。和 ip::tcp::resolver
。
DEBUG_MSG(" Protocol Initiated");
asio::ip::address_v4 address = asio::ip::address_v4::from_string(ip_);
tcp::endpoint ep(address, std::stoi(port_));
使用static mutex
很少有用。您的意思是同步对共享资源的访问吗?那么你也需要一个共享的互斥体
为什么要使用延迟锁?使用范围
{
//Critical Section start
std::lock_guard<std::mutex> lck(mutex_);
acceptor_ = tcp::acceptor(io_, ep);//Creating IOService
//Critical Section End
}
主线程刚刚退出,从未加入 io 线程。至少加入。或者在终止程序之前让它正确关闭:
t.join();
匈牙利语命名在这里真的没用。 sPtr
没有告诉我任何信息。 server
或者,如果你坚持,server_ptr
是你需要知道的。
你有越界写在这里:
received_[str.size()] = '\0';
你想要
received_[len] = '\0';
你的empty
不需要循环
bool empty() const
{
return !received_[0];
}
为什么要循环查找有序集中的东西?
std::set<sessionPtr>::iterator it;
for (it = sessions_.begin(); it != sessions_.end(); ++it)
{
if ((*it) == session)
{
sessions_.erase(session);
return;
}
}
应该是
sessions_.erase(session);
addSession/dropSession 在内部锁定;你不需要在关键部分访问它们
throw e
是一种反模式;只是throw;
被重新抛出
几乎所有地方都有冗余跟踪(这就是调试器的用途)。例如。 DEBUG_MSG("读取")
锁定这里是假的:
tcp::socket& socket()
{
// Critical Section
std::lock_guard<std::mutex> lock(mutex_);
return socket_;
}
返回的引用无论如何都不会受到保护,套接字只会被初始化一次。
因为只有一个服务线程,所有的线程锁似乎都是多余的
CBuffer msg
是 read()
的虚假参数,因为始终传递相同的缓冲区。这可能很好(在同一个 session 中),所以,只需使用它。
这个
acceptor_ = tcp::acceptor(io_, ep);
应该是
acceptor_.bind(ep);
并且不在关键部分(服务器只创建一次);因此 initProtocol
函数可以是
void initProtocol()
{
acceptor_.bind(tcp::endpoint(asio::ip::address_v4::from_string(ip_), std::stoi(port_)));
listen();
}
在 listen
中,您捕获了 bad_weak_ptr,它甚至不会发生
此处:
//Do I need a Lock here?
//Critical Section
std::lock_guard<std::mutex> lock(mutex_);
newSession->startSession();
你不需要锁。 newSession
是从局部变量绑定(bind)的。除非您复制了完成处理程序(您没有),否则它不可能被共享。
这是一个更固定的版本:
#include <iostream>
#include <boost/asio.hpp>
#include <memory>
#include <deque>
#include <set>
#include <iomanip>
#include <mutex>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#define DEBUG ON
#ifdef DEBUG
#define DEBUG_MSG(str) do {std::cout << std::setw(75) << std::left << __FUNCTION__ \
<< std::setw(3) << std::left << ":" << std::setw(5) << std::left << __LINE__ \
<< std::setw(5) << std::left << ":"\
<< std::left << str \
<< std::endl;} while( false )
#else
#define DEBUG_MSG(str) do { } while ( false )
#endif
namespace asio = boost::asio;
using asio::ip::tcp;
class CSerSession;
using sessionPtr = std::shared_ptr<CSerSession>;
class CSerSessionsManager {
private:
mutable std::mutex mutex_;
std::set<sessionPtr> sessions_; // Active Sessions : Online Info
public:
CSerSessionsManager();
~CSerSessionsManager();
void addSession(sessionPtr session);
void dropSession(sessionPtr session);
};
class CBuffer {
public:
enum { buffsize = 32 };
private:
char received_[buffsize];
public:
CBuffer() : received_{} {}
CBuffer(const std::string str)
{
// Truncate if Overflow
auto len = str.size();
if (len >= buffsize) {
len = buffsize - 1;
}
std::copy(str.begin(), str.begin() + len, received_);
received_[len] = '\0';
}
bool empty() const
{
return !received_[0];
}
const std::string getString() const { return std::string(received_); }
const char* getReceived() const { return received_; }
};
class CSerSession : public std::enable_shared_from_this<CSerSession> {
private:
mutable std::mutex mutex_;
mutable tcp::socket socket_; // client connection
CSerSessionsManager& manager_;
std::string ip_;
std::string port_;
CBuffer msg_;
public:
CSerSession(asio::io_service& io_service, CSerSessionsManager& mng) : socket_(io_service), manager_(mng)
{
DEBUG_MSG("Server Session Created");
}
~CSerSession() { DEBUG_MSG("Server Session Destroyed"); }
void startSession()
{
DEBUG_MSG("Server Session Started");
manager_.addSession(shared_from_this()); // Multiple threads should not try adding section
read();
}
tcp::socket& socket() { return socket_; }
private:
void handle_read(const boost::system::error_code& error /*error*/, size_t /*bytes_transferred*/)
{
if (!error) {
read();
} else {
DEBUG_MSG("Read Error Detected : " << error.message());
manager_.dropSession(shared_from_this()); // might throw
}
}
void read()
{
std::lock_guard<std::mutex> lock(mutex_);
DEBUG_MSG("Read");
asio::async_read(socket_, asio::buffer(const_cast<char*>(msg_.getReceived()), msg_.buffsize),
std::bind(&CSerSession::handle_read, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
}
};
CSerSessionsManager::CSerSessionsManager()
{
DEBUG_MSG("Construction");
}
CSerSessionsManager::~CSerSessionsManager()
{
DEBUG_MSG("Destruction");
}
void CSerSessionsManager::addSession(sessionPtr session)
{
std::lock_guard<std::mutex> lock(mutex_);
DEBUG_MSG("Incoming Session Entry saved");
sessions_.insert(session);
}
void CSerSessionsManager::dropSession(sessionPtr session)
{
std::lock_guard<std::mutex> lock(mutex_);
DEBUG_MSG("Session dropped");
sessions_.erase(session);
}
class CServer {
private:
mutable std::mutex mutex_;
asio::io_service& io_;
mutable tcp::acceptor acceptor_; // only in the listener
CSerSessionsManager mng_;
public:
CServer(asio::io_service& io_service, const std::string& IP, int port)
: io_(io_service), acceptor_(io_, tcp::endpoint(asio::ip::address::from_string(IP), port))
{
DEBUG_MSG("Listener Created");
}
~CServer()
{
DEBUG_MSG("Listener Destroyed");
acceptor_.close(); // likely to be redundant
}
void initProtocol()
{
listen();
}
private:
void listen()
{
DEBUG_MSG("!==============================================================!");
sessionPtr newSession = std::make_shared<CSerSession>(io_, mng_);
std::lock_guard<std::mutex> lock(mutex_);
acceptor_.async_accept(newSession->socket(), std::bind(&CServer::handle_accept, this, newSession,
std::placeholders::_1));
}
void handle_accept(sessionPtr newSession, const boost::system::error_code& error)
{
if (error || !acceptor_.is_open()) {
DEBUG_MSG("Listen_Error");
DEBUG_MSG(error.message());
return;
}
DEBUG_MSG("Incoming Session accepted");
newSession->startSession();
listen();
}
};
int main()
{
try
{
asio::io_service io_service;
auto server = std::make_shared<CServer>(io_service, "127.0.0.1", 8973);
server->initProtocol();
boost::thread t(boost::bind(&asio::io_service::run, &io_service));
boost::this_thread::sleep_for(boost::chrono::seconds(3));
t.join();
}
catch (...)
{
}
}
打印(对于单个连接):
CSerSessionsManager : 123 : Construction
CServer : 156 : Listener Created
listen : 173 : !==============================================================!
CSerSession : 86 : Server Session Created
handle_accept : 190 : Incoming Session accepted
startSession : 93 : Server Session Started
addSession : 134 : Incoming Session Entry saved
read : 114 : Read
listen : 173 : !==============================================================!
CSerSession : 86 : Server Session Created
handle_read : 106 : Read Error Detected : End of file
dropSession : 141 : Session dropped
~CSerSession : 89 : Server Session Destroyed
关于c++ - ASIO 聊天 session 类在销毁时抛出异常 : C++ ASIO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28564029/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!