草庐IT

c++ - Boost连接后从TCP服务器访问TCP客户端IP地址+端口

coder 2023-09-18 原文

我已经使用 boost asio 实现了一个 tcp 客户端和 tcp 服务器。代码如下。 (test.cpp、test.hpp 和 makefile)

可执行文件可以运行为

(服务器端)

$ ./client_server 1 5005

(客户端)

$ ./client_server 0 5005

tcp_server 类,当它接受连接时应该知道远程端点(client_ip 地址 + 客户端端口地址)。 但是似乎没有变量似乎将其存储在服务器端。我想存储客户端端点信息。我该怎么做?

测试.cpp

#include "test.hpp"
#include <iostream>
#include <exception>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <algorithm>
#include <sstream>
#include <iomanip>

const int ARG_COUNT = 2;
const int MAX_PACKETS = 25;
const int LOWEST_PORT = 1024;
const int HIGHEST_PORT = 65000;

static char message_array[8192];

void gen_random_string(char *s, const int len)
{
    static const char alphanum[] =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";

    for (int i = 0; i < len; ++i) {
        s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
    }
    s[len] = 0;
}

class tcp_connection :public boost::enable_shared_from_this<tcp_connection>
{
public:
    typedef boost::shared_ptr<tcp_connection> pointer;

    static pointer create(boost::asio::io_service& io_service)
    {
        return pointer(new tcp_connection(io_service));
    }

    boost::asio::ip::tcp::tcp::socket& socket()
    {
        return socket_;
    }

    void start()
    {
        gen_random_string(message_array, 8192);
        std::string message(message_array);

        boost::asio::async_write(socket_, boost::asio::buffer(message),
                                 boost::bind(&tcp_connection::handle_write, shared_from_this(),
                                             boost::asio::placeholders::error,
                                             boost::asio::placeholders::bytes_transferred));
    }

private:
    tcp_connection(boost::asio::io_service& io_service)
        : socket_(io_service)
    {
    }

    void handle_write(const boost::system::error_code& /*error*/,
                      size_t /*bytes_transferred*/)
    {
    }

    boost::asio::ip::tcp::socket socket_;
    std::string message;
};

class tcp_server
{
public:
    tcp_server(boost::asio::io_service& io_service,int port_number)
        : acceptor_(io_service, boost::asio::ip::tcp::tcp::endpoint(boost::asio::ip::tcp::tcp::v4(), port_number))
    {
        std::cout << "TCP server listening on " << port_number << std::endl;
        start_accept();
    }

private:
    void start_accept()
    {
        tcp_connection::pointer new_connection =
            tcp_connection::create(acceptor_.get_io_service());

        acceptor_.async_accept(new_connection->socket(),
                               boost::bind(&tcp_server::handle_accept, this, new_connection,
                                           boost::asio::placeholders::error));
    }

    void handle_accept(tcp_connection::pointer new_connection,
                       const boost::system::error_code& error)
    {
        if (!error)
        {
            new_connection->start();
            start_accept();
        }
    }

    boost::asio::ip::tcp::tcp::acceptor acceptor_;
};


void runTCPServer ( CmdLineOpts input )
{
    try
    {
        boost::asio::io_service io_service;
        tcp_server server(io_service,input.port);
        io_service.run();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }
}

class tcp_client
{
public:
    tcp_client(
        boost::asio::io_service& io_service,
        const std::string& host,
        const std::string& port
    ) : io_service_(io_service), socket_(io_service, boost::asio::ip::tcp::tcp::endpoint(boost::asio::ip::tcp::tcp::v4(), 0))
    {
        boost::asio::ip::tcp::tcp::resolver resolver(io_service_);
        boost::asio::ip::tcp::tcp::resolver::query query(boost::asio::ip::tcp::tcp::v4(), host, port);
        boost::asio::ip::tcp::tcp::resolver::iterator iter = resolver.resolve(query);
        endpoint_ = *iter;
        boost::asio::connect(socket_, iter);
    }

    ~tcp_client()
    {
        socket_.close();
    }


    void recieve_from() {
        /*Initialize our endpoint*/
        size_t len = socket_.read_some(
                         boost::asio::buffer(recv_buf), error);

        if (error == boost::asio::error::eof)
            std::cout << "Connction close cleanly by peer" << std::cout;
        else if (error)
            throw boost::system::system_error(error); // Some other error.

        std::cout.write(recv_buf.data(), len) << std::endl;

    }

private:
    boost::asio::io_service& io_service_;
    boost::asio::ip::tcp::tcp::socket socket_;
    boost::asio::ip::tcp::tcp::endpoint endpoint_;
    boost::array<char, 2048> recv_buf;
    boost::asio::ip::tcp::endpoint sender_endpoint;
    boost::system::error_code error;

};

void runTCPClient(std::string portStr)
{
    try
    {
        boost::asio::io_service io_service;
        tcp_client client(io_service, "localhost", portStr);
        client.recieve_from();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

}

void runClient( CmdLineOpts input )
{
    runTCPClient(input.portStr);

}

void runServer( CmdLineOpts input )
{
    runTCPServer(input);
}

/**
 * * Usage: client_server <protocol> <port> <num of packets>
 * */
bool cmdline_parse ( int argc, char *argv[], CmdLineOpts *input )
{
    bool result = true;
    if (argc - 1 == ARG_COUNT)
    {
        // arg 1: server or client
        int arg1 = std::stoi(argv[1]);
        if (arg1 == 0 || arg1 == 1)
        {
            input->servOrClient = arg1;
        }
        else
        {
            std::cout << "Invalid client server choice.\nUsage: client_server <client (0) or server(1)> <protocol> <port>" << std::endl;
            result = false;
        }
        // arg 3: port
        int arg2 = std::stoi(argv[2]);
        if (arg2 > LOWEST_PORT && arg2 < HIGHEST_PORT )
        {
            input->port = arg2;
            input->portStr = argv[2];
        }
        else
        {
            std::cout << "Invalid port, must be between " << LOWEST_PORT << " and " << HIGHEST_PORT << std::endl;
            std::cout << "Usage: client_server <client (0) or server(1)> <protocol> <port>" << std::endl;
            result = false;
        }

    }
    else
    {
        std::cout << "Usage: client_server <client (0) or server(1)> <protocol> <port>" << std::endl;
        result = false;
    }

    return result;
}



int main ( int argc, char *argv[] )
{
    CmdLineOpts input;
    if (cmdline_parse(argc, argv, &input))
    {
        if(input.servOrClient == 1)
        {
            runServer(input);
        }
        else if(input.servOrClient == 0)
        {
            runClient(input);
        }
    }
    else
    {
        return 1;
    }

    return 0;
}

测试.hpp

#ifndef CLIENT_SERVER_H_INCLUDED                                                                                                                                                                                   
#define CLIENT_SERVER_H_INCLUDED

#include <string>

struct CmdLineOpts
{
    std::string portStr;
    int port;
    int servOrClient;
};

void runTCPServer ( CmdLineOpts input );

void runTCPClient ( std::string port_str);

bool cmdline_parse ( int argc, char *argv[], CmdLineOpts input );
#endif

生成文件

TARGET = client_server                                                                                                                                                                                             
LIBS = -lboost_system -lpthread
CXX = g++ 
CXXFLAGS = -std=c++11 -g -Wall -pedantic

.PHONY: default all clean

default: $(TARGET)
all: default

OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp))
HEADERS = $(wildcard *.hpp)

%.o: %.cpp $(HEADERS)
  $(CXX) $(CXXFLAGS) -c $< -o $@

.PRECIOUS: $(TARGET) $(OBJECTS)

$(TARGET): $(OBJECTS)
  $(CXX) $(OBJECTS) $(LIBS) -o $@

clean:
      -rm -f *.o
      -rm -f $(TARGET)

最佳答案

可以调用socket_.remote_endpoint()获取。参见:

http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/basic_stream_socket/remote_endpoint.html

关于c++ - Boost连接后从TCP服务器访问TCP客户端IP地址+端口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35563701/

有关c++ - Boost连接后从TCP服务器访问TCP客户端IP地址+端口的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  5. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  6. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  7. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  8. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  9. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  10. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

随机推荐