首页 > 解决方案 > 制作 Boost::Asio chat_server 示例的头文件会给我“找到一个或多个定义的符号”错误

问题描述

我是 c++ 和 boost 库的新手,试图通过从这个例子中制作三个单独的文件来学习头文件。https://www.boost.org/doc/libs/1_70_0/doc/html/boost_asio/example/cpp11/chat/chat_server.cpp chat_message.hpp 在这里虽然我不认为这会导致问题。https://www.boost.org/doc/libs/1_70_0/doc/html/boost_asio/example/cpp11/chat/chat_message.hpp

目标是将示例分成三个部分。

  1. 主文件
  2. chat_server.h - 声明的头文件
  3. chat_server.cpp - 实现

这是我的实现,但我遇到了两个错误。

  1. 错误列表 -
LNK1169 > One or more multiple defined symbols found > File-> main.exe
LNK2005 > $dummy_return@asio@boost@@YAXXZ) already defined in chat_server.obj > file-> main.obj

输出

Build started...
1>------ Build started: Project: main, Configuration: Debug Win32 ------
1>main.obj : error LNK2005: "void __cdecl boost::asio::dummy_return<void>(void)" (??$dummy_return@X@asio@boost@@YAXXZ) already defined in chat_server.obj
1>C:\Users\Offline User\source\repos\main\Debug\main.exe : fatal error LNK1169: one or more multiply defined symbols found
1>Done building project "main.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

示例代码在分成三个之前运行良好。我不知道这是否与 typedef 或 virtual 有关,因为其他类和方法对我来说很容易理解(根据我在网上学到的)。请在这里帮助我,让我知道我在这里缺少什么?谢谢。

  1. 主文件
#include "chat_server.h"

int main(int argc, char* argv[])
{
    try
    {
        if (argc < 2)
        {
            std::cerr << "Usage: chat_server <port> [<port> ...]\n";
            return 1;
        }

        boost::asio::io_context io_context;

        std::list<chat_server> servers;
        for (int i = 1; i < argc; ++i)
        {
            tcp::endpoint endpoint(tcp::v4(), std::atoi(argv[i]));
            servers.emplace_back(io_context, endpoint);
        }

        io_context.run();
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}
  1. 聊天服务器.h
#ifndef CHAT_SERVER_H
#define CHAT_SERVER_H

#include <cstdlib>
#include <deque>
#include <iostream>
#include <list>
#include <memory>
#include <set>
#include <utility>
#include <boost/asio.hpp>
#include "chat_message.hpp"

using boost::asio::ip::tcp;

//----------------------------------------------------------------------

typedef std::deque<chat_message> chat_message_queue;

//----------------------------------------------------------------------

class chat_participant
{
public:
    virtual ~chat_participant() {};
    virtual void deliver(const chat_message& msg) = 0;
};

typedef std::shared_ptr<chat_participant> chat_participant_ptr;

//----------------------------------------------------------------------

class chat_room
{
public:
    void join(chat_participant_ptr participant);

    void leave(chat_participant_ptr participant);

    void deliver(const chat_message& msg);

private:
    std::set<chat_participant_ptr> participants_;
    enum { max_recent_msgs = 100 };
    chat_message_queue recent_msgs_;
};

//----------------------------------------------------------------------

class chat_session
    : public chat_participant,
    public std::enable_shared_from_this<chat_session>
{
public:
    chat_session(tcp::socket socket, chat_room& room);

    void start();

    void deliver(const chat_message& msg);

private:
    void do_read_header();

    void do_read_body();

    void do_write();

    tcp::socket socket_;
    chat_room& room_;
    chat_message read_msg_;
    chat_message_queue write_msgs_;
};

//----------------------------------------------------------------------

class chat_server
{
public:
    chat_server(boost::asio::io_context& io_context,
        const tcp::endpoint& endpoint);
private:
    void do_accept();

    tcp::acceptor acceptor_;
    chat_room room_;
};

#endif
  1. 聊天服务器.cpp
#include "chat_server.h"


void chat_room::join(chat_participant_ptr participant)
{
    participants_.insert(participant);
    for (auto msg : recent_msgs_)
        participant->deliver(msg);
}

void chat_room::leave(chat_participant_ptr participant)
{
    participants_.erase(participant);
}

void chat_room::deliver(const chat_message& msg)
{
    recent_msgs_.push_back(msg);
    while (recent_msgs_.size() > max_recent_msgs)
        recent_msgs_.pop_front();

    for (auto participant : participants_)
        participant->deliver(msg);
}

//----------------------------------------------------------------------
chat_session::chat_session(tcp::socket socket, chat_room& room)
    : socket_(std::move(socket)),
    room_(room)
{
}

void chat_session::start()
{
    room_.join(shared_from_this());
    do_read_header();
}

void chat_session::deliver(const chat_message& msg)
{
    bool write_in_progress = !write_msgs_.empty();
    write_msgs_.push_back(msg);
    if (!write_in_progress)
    {
        do_write();
    }
}

void chat_session::do_read_header()
{
    auto self(shared_from_this());
    boost::asio::async_read(socket_,
        boost::asio::buffer(read_msg_.data(), chat_message::header_length),
        [this, self](boost::system::error_code ec, std::size_t /*length*/)
        {
            if (!ec && read_msg_.decode_header())
            {
                do_read_body();
            }
            else
            {
                room_.leave(shared_from_this());
            }
        });
}

void chat_session::do_read_body()
{
    auto self(shared_from_this());
    boost::asio::async_read(socket_,
        boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
        [this, self](boost::system::error_code ec, std::size_t /*length*/)
        {
            if (!ec)
            {
                room_.deliver(read_msg_);
                do_read_header();
            }
            else
            {
                room_.leave(shared_from_this());
            }
        });
}

void chat_session::do_write()
{
    auto self(shared_from_this());
    boost::asio::async_write(socket_,
        boost::asio::buffer(write_msgs_.front().data(),
            write_msgs_.front().length()),
        [this, self](boost::system::error_code ec, std::size_t /*length*/)
        {
            if (!ec)
            {
                write_msgs_.pop_front();
                if (!write_msgs_.empty())
                {
                    do_write();
                }
            }
            else
            {
                room_.leave(shared_from_this());
            }
        });
}


//----------------------------------------------------------------------
chat_server::chat_server(boost::asio::io_context& io_context,
    const tcp::endpoint& endpoint)
    : acceptor_(io_context, endpoint)
{
    do_accept();
}

void chat_server::do_accept()
{
    acceptor_.async_accept(
        [this](boost::system::error_code ec, tcp::socket socket)
        {
            if (!ec)
            {
                std::make_shared<chat_session>(std::move(socket), room_)->start();
            }

            do_accept();
        });
}

标签: c++socketsboostheaderboost-asio

解决方案


https://github.com/chriskohlhoff/asio/pull/584

include/boost/asio/impl/use_awaitable.hpp有错误,dummy_return应标明inline

改变:

template <>
void dummy_return()
{
}

至:

template <>
inline void dummy_return()
{
}

推荐阅读