我正在运行 Xubuntu 14.04 和 Boost 1.54.0。我修改了 this book 中的第 4 章示例能够在客户端和服务器之间发送任意字符串,但现在程序立即失败。
这是服务器:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <string>
using namespace boost::asio;
io_service service;
size_t read_complete(
char* buff, const boost::system::error_code& err, size_t bytes)
{
if (err) {
return 0;
}
bool found = std::find(buff, buff + bytes, '\n') < buff + bytes;
return found? 0 : 1;
}
void handle_connections() {
ip::tcp::acceptor acceptor(
service, ip::tcp::endpoint(ip::tcp::v4(), 8001));
std::string buff;
while (true) {
ip::tcp::socket sock(service);
acceptor.accept(sock);
int bytes = read(sock, buffer(buff.c_str()), bind(read_complete, buff, _1, _2));
std::string msg(buff, bytes);
sock.write_some(buffer(msg));
sock.close();
}
}
int main(int argc, char* argv[]) {
handle_connections();
}
它是直接从书中复制的,并且已经过验证可以正常工作。
这是重现问题所需的最小客户端:
#include <memory>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
using namespace boost::asio;
class Client
{
public:
Client(const std::string& server, const std::string& port):
server(server), port(port)
{
service = std::unique_ptr<io_service>(new io_service);
endpoint = std::unique_ptr<ip::tcp::endpoint>(new ip::tcp::endpoint(
ip::address::from_string(server), atoi(port.c_str())));
boostSocket = std::unique_ptr<ip::tcp::socket>(
new ip::tcp::socket(*service));
std::cout << std::boolalpha << boostSocket.is_open(); // "false"
}
private:
std::string server;
std::string port;
std::unique_ptr<io_service> service;
std::unique_ptr<ip::tcp::socket> boostSocket;
std::unique_ptr<ip::tcp::endpoint> endpoint;
};
int main()
{
Client client("127.0.0.1", "8001");
return 0;
}
运行这个程序告诉我套接字从未打开。所以我深入研究了 GDB 并发现了这个。为方便起见,我省略了在每组行之间使用的 (gdb) s
调试命令。
Client::Client (this=0x7fffffffd7f8, server="127.0.0.1", port="8001")
at DIRECTORY WHERE I STORED THE CPP FILE:14
14 service = std::unique_ptr<io_service>(new io_service);
boost::asio::io_service::io_service (this=0x622130) at /usr/include/boost/asio/impl/io_service.ipp:41
41 {
boost::asio::detail::noncopyable::noncopyable (this=0x622130) at /usr/include/boost/asio/detail/noncopyable.hpp:29
29 noncopyable() {}
boost::asio::io_service::io_service (this=0x622130) at /usr/include/boost/asio/impl/io_service.ipp:39
39 (std::numeric_limits<std::size_t>::max)())),
std::numeric_limits<unsigned long>::max () at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/limits:1196
1196 max() _GLIBCXX_USE_NOEXCEPT { return __LONG_MAX__ * 2UL + 1; }
boost::asio::io_service::io_service (this=0x622130) at /usr/include/boost/asio/impl/io_service.ipp:41
41 {
boost::asio::detail::service_registry::service_registry<boost::asio::detail::task_io_service, unsigned long> (this=0x622150, o=..., arg=18446744073709551615)
at /usr/include/boost/asio/detail/impl/service_registry.hpp:29
29 {
boost::asio::detail::noncopyable::noncopyable (this=0x622150) at /usr/include/boost/asio/detail/noncopyable.hpp:29
29 noncopyable() {}
boost::asio::detail::posix_mutex::posix_mutex (this=0x622158) at /usr/include/boost/asio/detail/impl/posix_mutex.ipp:33
33 {
boost::asio::detail::noncopyable::noncopyable (this=0x622158) at /usr/include/boost/asio/detail/noncopyable.hpp:29
29 noncopyable() {}
boost::asio::detail::posix_mutex::posix_mutex (this=0x622158) at /usr/include/boost/asio/detail/impl/posix_mutex.ipp:34
34 int error = ::pthread_mutex_init(&mutex_, 0);
相关行是第一行(因为它是我代码的一部分)和最后一行(它直接进入错误处理)。随后的 GDB 命令仅表明它进一步深入了 Boost 的错误处理系统。为什么?我所做的只是创建一个 io_service
。
最佳答案
我必须修复客户端和服务器程序中的错误才能编译。
这是固定服务器:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <string>
using namespace boost::asio;
io_service service;
size_t read_complete(std::vector<char>const& buff, const boost::system::error_code &err, size_t bytes) {
if (err) {
return 0;
}
auto last = buff.begin()+bytes;
bool found = (last != std::find(buff.begin(), last, '\n'));
return found;
}
void handle_connections() {
ip::tcp::acceptor acceptor(service, ip::tcp::endpoint(ip::tcp::v4(), 8001));
std::vector<char> buff(1024);
while (true) {
ip::tcp::socket sock(service);
acceptor.accept(sock);
int bytes = read(sock, buffer(buff), bind(read_complete, boost::ref(buff), _1, _2));
sock.send(buffer(buff, bytes));
sock.close();
}
}
int main() { handle_connections(); }
有很多更改,最显着的是修复缓冲区的更改。
这是固定客户端。我摒弃了所有对 new
的迷信用法:
#include <memory>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
using namespace boost::asio;
class Client {
public:
Client(const std::string &server, const std::string &port)
: server(server),
port(port),
service(),
endpoint(ip::address::from_string(server), atoi(port.c_str())),
boostSocket(service)
{
std::cout << std::boolalpha << boostSocket.is_open() << "\n"; // of course, "false"
}
private:
std::string server;
std::string port;
io_service service;
ip::tcp::endpoint endpoint;
ip::tcp::socket boostSocket;
};
int main() {
Client client("127.0.0.1", "8001");
return 0;
}
注意事项:
您应该使用解析器来解析地址/端口,而不是仅仅对转换进行硬编码(它可能不是 IP 或端口号)
你永远不会连接,所以当然套接字没有打开
boostSocket.connect(endpoint); std::cout << std::boolalpha << boostSocket.is_open() << "\n"; // of connected, "true" /* *std::string message("hellow world\n\n\n\n\n"); *boostSocket.send(buffer(message)); *streambuf sb; *read(boostSocket, sb, boost::asio::transfer_all()); *std::cout << "RESPONSE: '" << &sb << "'\n"; */
调试愉快
关于c++ - 无法使简单的 boost 网络示例正常工作,仅仅初始化服务器会立即导致错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33252522/