[英]Boost ASIO - Unable to send message over TCP
I am using Boost ASIO for my TCP network communication.我正在使用 Boost ASIO 进行 TCP 网络通信。 Here is my code:
这是我的代码:
Server.h
: Server.h
:
#ifndef VIBRANIUM_CORE_SERVER_H
#define VIBRANIUM_CORE_SERVER_H
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
#include <deque>
#include "Logger.h"
#include "Client.h"
#include "Protocol/ServerOpcode.h"
using boost::asio::ip::tcp;
namespace Vibranium {
class Server {
public:
Server(boost::asio::io_service &io_service, short port)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
socket_(io_service) {
do_accept();
Logger::Log("Server Started! Listening on Port("+std::to_string(port)+")", Logger::Success, true);
}
static std::deque<std::shared_ptr<Client>> Clients;
private:
void do_accept();
int incrementor;
tcp::acceptor acceptor_;
tcp::socket socket_;
};
}
#endif //VIBRANIUM_CORE_SERVER_H
Server.cpp
: Server.cpp
:
#include "Server.h"
#include "Client.h"
using namespace Vibranium;
std::deque<std::shared_ptr<Client>> Server::Clients;
void Server::do_accept()
{
acceptor_.async_accept(socket_,
[this](boost::system::error_code ec)
{
if (!ec)
{
incrementor++;
Logger::Log("New Connection (ID: " + std::to_string(incrementor) + ")",Logger::Success);
std::shared_ptr<Client> c = std::make_shared<Client>(std::move(socket_));
c->start();
c->connectionId = incrementor;
Server::Clients.push_back(c);
}
do_accept();
});
}
Client.h
: Client.h
:
#ifndef VIBRANIUM_CORE_CLIENT_H
#define VIBRANIUM_CORE_CLIENT_H
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
#include "Protocol/ServerOpcode.h"
using boost::asio::ip::tcp;
namespace Vibranium{
class Client: public std::enable_shared_from_this<Client>
{
public:
Client(tcp::socket socket)
: socket(std::move(socket))
{
}
void start();
int connectionId;
tcp::socket socket;
void Send(ServerOpcode serverOpcode, const std::string& message);
private:
void do_read();
void do_write(std::size_t length);
enum { max_length = 1024 };
char data_[max_length];
};
}
#endif //VIBRANIUM_CORE_CLIENT_H
Client.cpp
: Client.cpp
:
#include "Client.h"
#include "Server.h"
void Vibranium::Client::start() {
do_read();
}
void Vibranium::Client::do_read() {
auto self(shared_from_this());
socket.async_read_some(boost::asio::buffer(data_, max_length),
[this, self](boost::system::error_code ec, std::size_t length)
{
if ((boost::asio::error::eof == ec) || (boost::asio::error::connection_reset == ec))
{
Logger::Log("Disconnected ID: " + std::to_string(connectionId),Logger::Error, true);
for (int i = 0; i < Server::Clients.size(); ++i) {
if(Server::Clients[i]->connectionId == connectionId)
Server::Clients.erase(Server::Clients.begin()+i);
}
}
else
{
std::cout.write(data_, length);
std::cout << "\n";
//do_write(length);
Send(ServerOpcode::SMSG_AUTH_CONNECTION_RESPONSE,"How are you, mate?");
}
});
}
void Vibranium::Client::do_write(std::size_t length) {
auto self(shared_from_this());
boost::asio::async_write(socket, boost::asio::buffer(data_, length),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec)
{
do_read();
}
});
}
void Vibranium::Client::Send(ServerOpcode serverOpcode, const std::string& message) {
auto self(shared_from_this());
std::cout << "HERE!" << std::endl;
size_t request_length = std::strlen(message.c_str());
boost::asio::async_write(socket, boost::asio::buffer(message.c_str(), request_length),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec)
do_read();
else
Logger::Log("Message sent failed to " + std::to_string(connectionId),Logger::Error);
});
}
Here is how I simulate several connections to the server:这是我模拟到服务器的多个连接的方法:
Config config("AuthServer");
std::string defaultIP = "127.0.0.1";
std::string defaultPort = "8080";
int connectionsNumber = CommandQuestion<int>::AskQuestion("How many connections do you want established?");
std::cout << "Initializing " << std::to_string(connectionsNumber) << " connection/s." << std::endl;
std::cout << "Trying to connect to " << defaultIP << " on port: " << config.GetConfigValue("AuthServerPort", defaultPort) << std::endl;
boost::asio::io_context io_context;
std::vector<tcp::socket> sockets;
for (int i = 0; i < connectionsNumber; ++i) {
try
{
sockets.emplace_back(io_context);
tcp::socket& s{sockets.back()};
tcp::resolver resolver(io_context);
boost::asio::connect(s, resolver.resolve( defaultIP,config.GetConfigValue("AuthServerPort", defaultPort)));
std::string message = "I am testing here!!!";
size_t request_length = std::strlen(message.c_str());
boost::asio::write(s, boost::asio::buffer(message, request_length));
char reply[max_length];
size_t reply_length = boost::asio::read(s,boost::asio::buffer(reply, request_length));
Logger::Log(std::to_string(i) + " Connected!",Logger::Success);
std::cout << "Reply is: ";
std::cout.write(reply, reply_length);
std::cout << "\n";
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
} }
So basically I am establishing connection and then the clients sends a message to the server saying I am testing here!!!
所以基本上我正在建立连接,然后客户端向服务器发送一条消息,说
I am testing here!!!
than I would like to use my function Send
to send back to the client another message How are you, mate?
比我想使用我的功能
Send
发送回客户端另一条消息How are you, mate?
. .
However it does not work.但是它不起作用。 It seems the message can't be seen back from the client.
似乎无法从客户端看到该消息。 On server side I see the output of
HERE!
在服务器端,我看到
HERE!
的输出HERE!
which is located in Send
function.它位于
Send
功能中。 That means I reach that point.这意味着我达到了那个点。
On another hand if I uncomment //do_write(length);
另一方面,如果我取消注释
//do_write(length);
from function do_read()
and comment back send()
it seems to return back the message I am testing here!!!
从函数
do_read()
并评论回send()
似乎返回了I am testing here!!!
的消息I am testing here!!!
. . So by my understanding communication works that way.
所以根据我的理解,沟通是这样工作的。
My question is where is my mistake with Send
function?我的问题是我的
Send
功能错误在哪里? Why I can't make it send another message instead of just replying back with what the client sent in first place.为什么我不能让它发送另一条消息,而不仅仅是回复客户端首先发送的消息。
I found myself where the error was, here is how I solved it:我发现自己的错误在哪里,这是我解决它的方法:
void Vibranium::Client::Send(ServerOpcode serverOpcode, const std::string& message) {
auto self(shared_from_this());
std::cout << "HERE!" << std::endl;
strcpy(data_, message.c_str());
size_t request_length = sizeof(data_)/sizeof(*data_);
boost::asio::async_write(socket, boost::asio::buffer(data_, request_length),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
if (ec)
Logger::Log("Message sent failed to " + std::to_string(connectionId),Logger::Error);
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.