Poco TCPServer does not start outside main - c++

When i do the initialisation of the TCPServer inside of main it works, when i try to start it with the startServer() function it is not working, i mean i can not establish a connection with putty.
What am i doing wrong here?
Thanks for any help.
class EchoConnection : public TCPServerConnection {
public:
EchoConnection(const StreamSocket& s)
: TCPServerConnection(s) {}
void reply(char buffer[])
{
bzero(buffer, 256);
std::string myWord = "myWord\n\r";
strcpy(buffer, myWord.c_str());
}
void run() {
StreamSocket& ss = socket();
try {
char buffer[256];
int n = ss.receiveBytes(buffer, sizeof(buffer));
while (n > 0) {
reply(buffer);
ss.sendBytes(buffer, sizeof(buffer));
n = ss.receiveBytes(buffer, sizeof(buffer));
}
}
catch (Poco::Exception& exc)
{ std::cerr << "EchoConnection: " << exc.displayText() << std::endl; }
}
};
void startServer()
{
Poco::Net::TCPServer srv(new Poco::Net::TCPServerConnectionFactoryImpl<EchoConnection>, 8089);
srv.start();
SocketAddress sa("localhost", srv.socket().address().port());
StreamSocket ss(sa);
std::string data("hello, world");
ss.sendBytes(data.data(), (int)data.size());
char buffer[256] = { 0 };
int n = ss.receiveBytes(buffer, sizeof(buffer));
std::cout << std::string(buffer, n) << std::endl;
}
int main(int argc, char** argv) {
Poco::Net::TCPServer srv(new Poco::Net::TCPServerConnectionFactoryImpl<EchoConnection>, 8089);
srv.start();
SocketAddress sa("localhost", srv.socket().address().port());
StreamSocket ss(sa);
std::string data("hello, world");
ss.sendBytes(data.data(), (int)data.size());
char buffer[256] = { 0 };
int n = ss.receiveBytes(buffer, sizeof(buffer));
std::cout << std::string(buffer, n) << std::endl;
// startServer(8089);
ModuleData modData;
modData.ModuleNumber = 1;
modData.ModuleTypeId = 1;
string test = modData.serialize();
ifstream dataFile;
dataFile.open("ModuleData.dat");
if (dataFile.is_open())
{
string line;
while (getline(dataFile, line))
{
cout << line << std::endl;
}
dataFile.close();
}
while (1)
{
}
srv.stop();
}

At the end of startServer function srv object is deleted. TCPServer uses own thread but it finishes working in destructor of TCPServer.
Look at implementation of ~TCPServer
TCPServer::~TCPServer() {
try {
stop();
_pDispatcher->release();
...
}
and see stop method implementation
void TCPServer::stop() {
if (!_stopped)
{
_stopped = true; // !!
_thread.join(); // waiting for thread
_pDispatcher->stop();
}
}
the body of thread function is in run method
void TCPServer::run()
{
while (!_stopped) // this flag was set by stop method
{
... // body of thread function
}
}
stop method sets _stopped on true, and for this reason thread finishes working.

Related

boost::asio SerialPort unable to receive data

I am unable to receive data over serial port in boost::asio while using asynchronous. When I use synchronous routines I am able to receive data.
Code :
SerialPort.cpp
bool SerialPort::read_async(std::uint32_t read_timeout)
{
try
{
if (read_timeout not_eq SerialPort::ignore_timeout)
this->read_timeout = read_timeout;//If read_timeout is not set to ignore_timeout, update the read_timeout else use old read_timeout
this->port.async_read_some(boost::asio::buffer(this->read_buffer.data(), this->read_buffer.size()),
boost::bind(&SerialPort::read_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
return true;
}
catch (const std::exception& ex)
{
PLOG_ERROR << ex.what();
return false;
}
}
void SerialPort::read_handler(const boost::system::error_code& error, std::size_t bytes_transferred)
{
std::string received_data_buffer;
std::transform(this->read_buffer.begin(), this->read_buffer.begin() + bytes_transferred,
std::back_inserter(received_data_buffer), [](std::byte character) {
return static_cast<char>(character);
});
PLOG_INFO << "In Read Buffer : " << received_data_buffer;
}
bool SerialPort::open_port(void)
{
try
{
this->port.open(this->port_name);
return true;
}
catch (const std::exception& ex)
{
PLOG_FATAL << ex.what();
}
return false;
}
SerialPort.hpp
class SerialPort
{
private:
boost::asio::io_context io;
boost::asio::serial_port port;
boost::asio::serial_port::native_handle_type native_port;
std::string port_name;
const static std::uint32_t READ_BUFFER_MAX_LENGTH{ 8096 };
std::array<std::byte, SerialPort::READ_BUFFER_MAX_LENGTH> read_buffer;//Used in synchronous read
void read_handler(
const boost::system::error_code& error, // Result of operation.
std::size_t bytes_transferred // Number of bytes read.
);
//boost::asio::deadline_timer timer;
public:
SerialPort() : io(), port(io), thread_sync_read()
{
}
~SerialPort();
bool open_port(void);
bool read_async(std::uint32_t read_timeout = SerialPort::ignore_timeout);
};
main.cpp
SerialPort sp;
int main()
{
sp.open_port("COM11");
sp.write_sync("Testing123");
sp.read_async();
while (true)
{
}
return 0;
}
You're supposedly trying to do some operations asynchronously.
Firstly, mixing synchronous and asynchronous operations is not always advisable. Some services/IO objects might hold inner state that assumes one or the other.
Secondly, the asynchronous operation requires the io_service to be run. That doesn't happen. You could make it explicit instead of the current while() loop.
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
namespace asio = boost::asio;
using boost::system::error_code;
std::ostream PLOG_INFO(std::clog.rdbuf());
std::ostream PLOG_ERROR(std::clog.rdbuf());
std::ostream PLOG_FATAL(std::clog.rdbuf());
class SerialPort
{
public:
SerialPort()
: io_()
, port_(io_) /*, thread_sync_read()*/
{}
~SerialPort() = default;
bool open_port(std::string name);
static constexpr uint32_t ignore_timeout = -1;
bool read_async(std::uint32_t read_timeout = SerialPort::ignore_timeout);
void run() { io_.run(); }
private:
static constexpr uint32_t READ_BUFFER_MAX_LENGTH{8096};
asio::io_context io_;
asio::serial_port port_;
std::string port_name_;
uint32_t read_timeout_ = ignore_timeout;
// asio::deadline_timer timer;
std::array<std::byte, READ_BUFFER_MAX_LENGTH> read_buffer_;
void read_handler(error_code error, size_t bytes_transferred);
};
bool SerialPort::read_async(std::uint32_t read_timeout) {
try {
if (read_timeout != SerialPort::ignore_timeout)
read_timeout_ =
read_timeout; // If read_timeout is not set to ignore_timeout,
// update the read_timeout else use old
// read_timeout
port_.async_read_some(
asio::buffer(read_buffer_.data(), read_buffer_.size()),
boost::bind(&SerialPort::read_handler, this,
asio::placeholders::error,
asio::placeholders::bytes_transferred));
return true;
} catch (const std::exception& ex) {
PLOG_ERROR << ex.what() << std::endl;
return false;
}
}
void SerialPort::read_handler(error_code error, size_t bytes_transferred) {
std::string s;
std::transform(
read_buffer_.begin(), read_buffer_.begin() + bytes_transferred,
std::back_inserter(s),
[](std::byte character) { return static_cast<char>(character); });
PLOG_INFO << "In Read Buffer : " << s << " (" << error.message() << ")" << std::endl;
}
bool SerialPort::open_port(std::string name) {
try {
port_name_ = std::move(name);
port_.open(port_name_);
return true;
} catch (std::exception const& ex) {
PLOG_FATAL << ex.what() << std::endl;
return false;
}
}
SerialPort sp;
int main(int argc, char** argv) {
sp.open_port(argc > 1 ? argv[1] : "COM11");
// sp.write_sync("Testing123");
sp.read_async();
sp.run();
}

Unix domain sockets with Poco::Net::TCPServer

I created a TCPServer using the Poco::Net::TCPServer framework, that uses a unix domain socket and it seems to work. However if I close the server and start it again I get this error:
Net Exception: Address already in use: /tmp/app.SocketTest
What is the right way to deal with this error?
Are the TCPServerConnections, TCPServerConnectionFactory and sockets
automatically cleaned-up or do I need to implement their destructors or destroy them manually?
EDIT
I have two questions here. The first is answered by using remove() on the socket-file. The other question is, if the clean-up in the Poco::Net::TCPServer framework is automatic or if it has to be manually implemented to prevent memory-leak?
Here is the code for the TCPServer:
#include "Poco/Util/ServerApplication.h"
#include "Poco/Net/TCPServer.h"
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/File.h"
#include <fstream>
#include <iostream>
using Poco::Net::ServerSocket;
using Poco::Net::StreamSocket;
using Poco::Net::TCPServer;
using Poco::Net::TCPServerConnection;
using Poco::Net::TCPServerConnectionFactory;
using Poco::Net::SocketAddress;
using Poco::Util::ServerApplication;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
class UnixSocketServerConnection: public TCPServerConnection
/// This class handles all client connections.
{
public:
UnixSocketServerConnection(const StreamSocket& s):
TCPServerConnection(s)
{
}
void run()
{
try
{
/*char buffer[1024];
int n = 1;
while (n > 0)
{
n = socket().receiveBytes(buffer, sizeof(buffer));
EchoBack(buffer);
}*/
std::string message;
char buffer[1024];
int n = 1;
while (n > 0)
{
n = socket().receiveBytes(buffer, sizeof(buffer));
buffer[n] = '\0';
message += buffer;
if(sizeof(buffer) > n && message != "")
{
EchoBack(message);
message = "";
}
}
}
catch (Poco::Exception& exc)
{
std::cerr << "Error: " << exc.displayText() << std::endl;
}
std::cout << "Disconnected." << std::endl;
}
private:
inline void EchoBack(std::string message)
{
std::cout << "Message: " << message << std::endl;
socket().sendBytes(message.data(), message.length());
}
};
class UnixSocketServerConnectionFactory: public TCPServerConnectionFactory
/// A factory
{
public:
UnixSocketServerConnectionFactory()
{
}
TCPServerConnection* createConnection(const StreamSocket& socket)
{
std::cout << "Got new connection." << std::endl;
return new UnixSocketServerConnection(socket);
}
private:
};
class UnixSocketServer: public Poco::Util::ServerApplication
/// The main application class.
{
public:
UnixSocketServer(): _helpRequested(false)
{
}
~UnixSocketServer()
{
}
protected:
void initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
ServerApplication::initialize(self);
}
void uninitialize()
{
ServerApplication::uninitialize();
}
void defineOptions(OptionSet& options)
{
ServerApplication::defineOptions(options);
options.addOption(
Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false));
}
void handleOption(const std::string& name, const std::string& value)
{
ServerApplication::handleOption(name, value);
if (name == "help")
_helpRequested = true;
}
void displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("A server application to test unix domain sockets.");
helpFormatter.format(std::cout);
}
int main(const std::vector<std::string>& args)
{
if (_helpRequested)
{
displayHelp();
}
else
{
// set-up unix domain socket
Poco::File socketFile("/tmp/app.SocketTest");
SocketAddress unixSocket(SocketAddress::UNIX_LOCAL, socketFile.path());
// set-up a server socket
ServerSocket svs(unixSocket);
// set-up a TCPServer instance
TCPServer srv(new UnixSocketServerConnectionFactory, svs);
// start the TCPServer
srv.start();
// wait for CTRL-C or kill
waitForTerminationRequest();
// Stop the TCPServer
srv.stop();
}
return Application::EXIT_OK;
}
private:
bool _helpRequested;
};
int main(int argc, char **argv) {
UnixSocketServer app;
return app.run(argc, argv);
}
You don't need to worry about deallocating memory. All is done by library.
TCPServer srv(new UnixSocketServerConnectionFactory, svs);
^^^
Instance of UnixSocketServerConnectionFactory is deleted by TCPServer according to poco ref
The server takes ownership of the TCPServerConnectionFactory and
deletes it when it's no longer needed.
TCPServerConnection* createConnection(const StreamSocket& socket)
{
std::cout << "Got new connection." << std::endl;
return new UnixSocketServerConnection(socket);
^^^
}
instances of UnixSocketServerConnection are deleted by Poco library code as well:
As soon as the run() method returns, the server connection object is
destroyed and the connection is automatically closed.
The problem with Poco::File was that the destructor of Poco::File cannot remove file, you have to do it explicitly by remove method.

ZeroMQ PUB/SUB bind subscriber

I'm studying ZeroMQ with myself.
I tested PUB as a server(bind), SUB as a client(connect) and worked fine. Opposite (PUB as a client(connect), SUB as a server(bind)) also works fine.
When I connect a another SUB socket as client something goes wrong without any exception or errors.
here's my example code.
#include <zmq.hpp>
#include <string>
#include <iostream>
#include <unistd.h>
#include <thread>
class ZMQSock
{
public:
ZMQSock(const char* addr)
{
if (addr != NULL)
{
mctx = new zmq::context_t(1);
mszAddr = new char[strlen(addr) + 1];
snprintf(mszAddr, strlen(addr) + 1, "%s", addr);
}
}
virtual ~ZMQSock()
{
if (msock != nullptr)
delete msock;
if (mctx != nullptr)
delete mctx;
if (mszAddr != nullptr)
delete [] mszAddr;
}
int zbind()
{
if (msock != nullptr)
msock->bind(mszAddr);
else return -1;
return 0;
}
int zconnect()
{
if (msock != nullptr)
msock->connect(mszAddr);
else return -1;
return 0;
}
void start()
{
if (mbthread != false)
return ;
mbthread = true;
mhthread = std::thread(std::bind(&ZMQSock::run, this));
}
virtual void stop()
{
if (mbthread == false)
return ;
mbthread = false;
if (mhthread.joinable())
mhthread.join();
}
virtual void run() = 0;
protected:
char* mszAddr{nullptr};
zmq::context_t* mctx{nullptr};
zmq::socket_t* msock{nullptr};
bool mbthread{false};
std::thread mhthread;
};
class ZPublisher : public ZMQSock
{
public:
ZPublisher(const char* addr) : ZMQSock(addr)
{
if (msock == nullptr)
{
msock = new zmq::socket_t(*mctx, ZMQ_PUB);
}
}
virtual ~ZPublisher()
{
}
bool zsend(const char* data, const unsigned int length, bool sendmore=false)
{
zmq::message_t msg(length);
memcpy(msg.data(), data, length);
if (sendmore)
return msock->send(msg, ZMQ_SNDMORE);
return msock->send(msg);
}
void run()
{
if (mszAddr == nullptr)
return ;
if (strlen(mszAddr) < 6)
return ;
const char* fdelim = "1";
const char* first = "it sends to first. two can not recv this sentence!\0";
const char* sdelim = "2";
const char* second = "it sends to second. one can not recv this sentence!\0";
while (mbthread)
{
zsend(fdelim, 1, true);
zsend(first, strlen(first));
zsend(sdelim, 1, true);
zsend(second, strlen(second));
usleep(1000 * 1000);
}
}
};
class ZSubscriber : public ZMQSock
{
public:
ZSubscriber(const char* addr) : ZMQSock(addr)
{
if (msock == nullptr)
{
msock = new zmq::socket_t(*mctx, ZMQ_SUB);
}
}
virtual ~ZSubscriber()
{
}
void setScriberDelim(const char* delim, const int length)
{
msock->setsockopt(ZMQ_SUBSCRIBE, delim, length);
mdelim = std::string(delim, length);
}
std::string zrecv()
{
zmq::message_t msg;
msock->recv(&msg);
return std::string(static_cast<char*>(msg.data()), msg.size());
}
void run()
{
if (mszAddr == nullptr)
return ;
if (strlen(mszAddr) < 6)
return ;
while (mbthread)
{
std::cout << "MY DELIM IS [" << mdelim << "] - MSG : ";
std::cout << zrecv() << std::endl;
usleep(1000 * 1000);
}
}
private:
std::string mdelim;
};
int main ()
{
ZPublisher pub("tcp://localhost:5252");
ZSubscriber sub1("tcp://localhost:5252");
ZSubscriber sub2("tcp://*:5252");
pub.zconnect();
sub1.zconnect();
sub2.zbind();
sub1.setScriberDelim("1", 1);
sub2.setScriberDelim("2", 1);
pub.start();
std::cout << "PUB Server has been started.." << std::endl;
usleep(1000 * 1000);
sub1.start();
std::cout << "SUB1 Start." << std::endl;
sub2.start();
std::cout << "SUB2 Start." << std::endl;
int i = 0;
std::cout << "< Press any key to exit program. >" << std::endl;
std::cin >> i;
std::cout << "SUB1 STOP START" << std::endl;
sub1.stop();
std::cout << "SUB2 STOP START" << std::endl;
sub2.stop();
std::cout << "PUB STOP START" << std::endl;
pub.stop();
std::cout << "ALL DONE" << std::endl;
return 0;
}
What causes this? or Am I using PUB/SUB illegally?
You are connecting a SUB socket to a SUB socket, that is an invalid connection. In your case the PUB should bind and the SUBs should connect.

Pthread loop function never gets called

Below is my code, my problem is that readEvent() function never gets called.
Header file
class MyServer
{
public :
MyServer(MFCPacketWriter *writer_);
~MyServer();
void startReading();
void stopReading();
private :
MFCPacketWriter *writer;
pthread_t serverThread;
bool stopThread;
static void *readEvent(void *);
};
CPP file
MyServer::MyServer(MFCPacketWriter *writer_):writer(writer_)
{
serverThread = NULL;
stopThread = false;
LOGD(">>>>>>>>>>>>> constructed MyServer ");
}
MyServer::~MyServer()
{
writer = NULL;
stopThread = true;
}
void MyServer::startReading()
{
LOGD(">>>>>>>>>>>>> start reading");
if(pthread_create(&serverThread,NULL,&MyServer::readEvent, this) < 0)
{
LOGI(">>>>>>>>>>>>> Error while creating thread");
}
}
void *MyServer::readEvent(void *voidptr)
{
// this log never gets called
LOGD(">>>>>>>>>>>>> readEvent");
while(!MyServer->stopThread){
//loop logic
}
}
Another class
MyServer MyServer(packet_writer);
MyServer.startReading();
Since you are not calling pthread_join, your main thread is terminating without waiting for your worker thread to finish.
Here is a simplified example that reproduces the problem:
#include <iostream>
#include <pthread.h>
class Example {
public:
Example () : thread_() {
int rcode = pthread_create(&thread_, nullptr, Example::task, nullptr);
if (rcode != 0) {
std::cout << "pthread_create failed. Return code: " << rcode << std::endl;
}
}
static void * task (void *) {
std::cout << "Running task." << std::endl;
return nullptr;
}
private:
pthread_t thread_;
};
int main () {
Example example;
}
View Results
No output is produced when running this program, even though pthread_create was successfully called with Example::task as the function parameter.
This can be fixed by calling pthread_join on the thread:
#include <iostream>
#include <pthread.h>
class Example {
public:
Example () : thread_() {
int rcode = pthread_create(&thread_, nullptr, Example::task, nullptr);
if (rcode != 0) {
std::cout << "pthread_create failed. Return code: " << rcode << std::endl;
}
}
/* New code below this point. */
~Example () {
int rcode = pthread_join(thread_, nullptr);
if (rcode != 0) {
std::cout << "pthread_join failed. Return code: " << rcode << std::endl;
}
}
/* New code above this point. */
static void * task (void *) {
std::cout << "Running task." << std::endl;
return nullptr;
}
private:
pthread_t thread_;
};
int main () {
Example example;
}
View Results
Now the program produces the expected output:
Running task.
In your case, you could add a call to pthread_join to the destructor of your MyServer class.

Boost asio, shared_from_this() error R6010, and async_read() eof

I'm trying to make a chat with boost asio, having the officals example as reference. But i'm actually having two problems with async_read, first, why do I have an EoF(end of file) and my connexion(and application) close so quickly in the client?
And then I have a problem in the async_read of ChatParticipant : if I pass "Shared_from_this()" as second argument of boost::bind I get and error R6010, but if i pass a simple "this", I don't have it.
Thanks for your help :)
Here is my concerned code :
Chat Server
class ChatServer
{
public:
ChatServer(boost::asio::io_service& io_service, const tcp::endpoint& endpoint): _io_service(io_service), _acceptor(io_service, endpoint)
{
startAccept();
}
void startAccept()
{
std::cout << "accepting a new client" << std::endl;
shared_ptr<ServerParticipant> newParticipant(new ServerParticipant(_io_service, &_room));
_acceptor.async_accept(newParticipant->getSocket(), boost::bind(&ChatServer::handleAccept, this, boost::asio::placeholders::error, newParticipant));
}
void handleAccept(const boost::system::error_code& e, shared_ptr<ServerParticipant> newParticipant)
{
if (!e)
{
std::cout << "accepted a new client" << std::endl;
boost::asio::async_read(newParticipant->getSocket(),
boost::asio::buffer(_readMsgCache.getAllMessage(), ChatMessage::header_length),
boost::bind(&ChatServer::read, this,
boost::asio::placeholders::error));
//newParticipant->start();
startAccept();
}
else
{
std::cerr << e.message() << std::endl;
}
}
void read(const boost::system::error_code& e)
{
if (e && e == boost::asio::error::eof)
{
std::cerr << "closed" << std::endl;
}
if (e)
{
std::cerr << e.message() << std::endl;
}
else
{
std::cout << "Reaaad" << std::endl;
}
}
private:
boost::asio::io_service& _io_service;
tcp::acceptor _acceptor;
ChatMessage _readMsgCache;
}
Chat Participant
class ChatParticipant : public boost::enable_shared_from_this<ChatParticipant>
{
public :
ChatParticipant(boost::asio::io_service& service) : _id(0), _service(service), _socket(service)
{}
virtual void start()
{
startRead();
}
void startRead()
{
std::cout << "Start read" << std::endl;
boost::asio::async_read(_socket,
boost::asio::buffer(_readMsgCache.getAllMessage(), 4),
boost::bind(
&ChatParticipant::readHeader, shared_from_this(),
boost::asio::placeholders::error));
}
// some functions about decoding the message...
protected:
int _id;
boost::asio::io_service& _service;
tcp::socket _socket;
std::deque<ChatMessage> _writeMsgCache;
ChatMessage _readMsgCache;
Chat Client
using boost::asio::ip::tcp;
class ChatClient
{
public:
ChatClient(boost::asio::io_service& service, tcp::endpoint& endpoint) : _service(service), _client(service)
{
_client.getSocket().async_connect(endpoint, boost::bind(&ChatClient::handleConnect, this, boost::asio::placeholders::error));
}
void handleConnect(const boost::system::error_code& err)
{
if (err)
{
std::cerr << err.message();
}
else
{
_client.start();
/*
ChatMessage message;
message.setMessage("hello");
_client.speak(message);
*/
}
}
void read(const boost::system::error_code& e)
{
if (e)
{
std::cerr << e.message() << std::endl;
}
else
{
std::cout << "Reaaad" << std::endl;
}
}
protected :
boost::asio::io_service& _service;
ChatParticipant _client;
};
ChatMessage
#pragma once
#include <stdlib.h>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
using namespace std;
class ChatMessage
{
public :
enum{header_length = 4};
static const size_t headerLength = 4;
static const size_t maxMsgLength = 512;
ChatMessage()
{
clear();
}
void clear()
{
for (size_t i = 0; i <= maxLength() ; ++i)
_allMessage[i] = '\0';
}
char* getAllMessage()
{
return _allMessage;
}
const char* getAllMessage() const
{
return _allMessage;
}
char* getBody()
{
return _allMessage + headerLength;
}
size_t getBodyLength()
{
return _bodyLength;
}
size_t length()
{
return headerLength + _bodyLength;
}
const size_t length() const
{
return headerLength + _bodyLength;
}
size_t maxLength()
{
return headerLength + maxMsgLength;
}
bool setBody(const char* message)
{
_bodyLength = strlen(message);
if (_bodyLength > maxMsgLength)
return false;
memcpy(getBody(), message, _bodyLength);
return true;
}
bool setMessage(const char* message)
{
clear();
if (!setBody(message))
return false;
encodeHeader();
return true;
}
#pragma warning(disable: 4996) /* Disable deprecation */
bool decodeHeader()
{
char header[headerLength + 1] = "";
strncat(header, _allMessage, headerLength);
_bodyLength = atoi(header);
if (_bodyLength > maxMsgLength)
return false;
return true;
}
void encodeHeader()
{
stringstream ss;
ss << setw(headerLength) << _bodyLength;
string s(ss.str());
memcpy(_allMessage,s.c_str(), headerLength);
}
private :
char _allMessage[headerLength + maxMsgLength];
size_t _bodyLength;
};
main
#include "ChatMessage.h"
#define IsServer true
#ifdef IsServer
#include "ChatServer.h"
#else
#include "ChatCLient.h"
#endif
using boost::asio::ip::tcp;
int main()
{
boost::asio::io_service service;
#ifdef IsServer
tcp::endpoint endpoint(tcp::v4(), 13);
std::cout << "Server start" << std::endl;
ChatServer server(service, endpoint);
#else
tcp::endpoint endpoint(boost::asio::ip::address_v4::from_string("127.0.0.1"), 13);
std::cout << "Client start" << std::endl;
ChatClient client(service, endpoint);
#endif
service.run();
return 0;
}
The R6010 error is probably caused by an uncaught exception. shared_from_this() is based on a weak pointer and its operation depends upon the object being the target of a shared pointer.
That is:
shared_ptr<ChatClient> client1 (new ChatClient);
// this client can use shared_from_this()
but
ChatClient client2;
// this client cannot use shared_from_this().
change
ChatParticipant _client;
to
boost::shared_ptr<ChatParticipant> _client;
and initialize the _client pointer in the ctor initialization list. This will allow you to invoke shared_from_this() to get a shared_ptr to _client.