我正在运行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
。
答案 0 :(得分:1)
我必须修复客户端和服务器程序中的错误才能编译。
这是固定服务器:
#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";
*/
快乐调试