公式の例を参考にして、boost asioとチャットしようとしています。しかし、私は実際に async_read で 2 つの問題を抱えています。まず、クライアントで EoF (ファイルの終わり) と接続 (およびアプリケーション) がすぐに閉じるのはなぜですか?
そして、ChatParticipant の async_read に問題があります。boost::bind の 2 番目の引数として「Shared_from_this()」を渡すと、エラー R6010 が発生しますが、単純な「this」を渡すと、それがありません。 .
ご協力いただきありがとうございます :)
ここに私の関係するコードがあります:
チャットサーバー
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;
}
チャット参加者
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;
チャット クライアント
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;
};
チャットメッセージ
#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;
};
主要
#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;
}