问题描述
我已实施 udp_client
并在服务器和客户机采用拉模式udp_server`。服务器推只有数据当客户端请求的。我想,当数据可用来改变这种推模型中,服务器将这些数据推到客户端。
I have implemented udp_client
and 'udp_server` where server and client follows a pull model. The server pushes the data only when the client requests it. I want to change this to push model where server pushes the data down to the client when data is available.
我的源文件,头文件,并作出如下。
My source files, header files and make is given below.
udp_server.cpp
udp_server.cpp
#include "udp_server.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 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 udp_server
{
public:
udp_server(boost::asio::io_service& io_service,int port_number)
: socket_(io_service, boost::asio::ip::udp::udp::endpoint(boost::asio::ip::udp::udp::v4(), port_number))
{
std::cout << "UDP server listening on " << port_number << std::endl;
start_receive();
}
private:
void start_receive()
{
socket_.async_receive_from(
boost::asio::buffer(recv_buffer_), remote_endpoint_,
boost::bind(&udp_server::handle_receive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void handle_receive(const boost::system::error_code& error,
std::size_t /*bytes_transferred*/)
{
if (!error || error == boost::asio::error::message_size)
{
gen_random_string(message_array, 8192);
boost::shared_ptr<std::string> message(new std::string(message_array));
socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,
boost::bind(&udp_server::handle_send, this, message,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
start_receive();
}
}
void handle_send(boost::shared_ptr<std::string> /*message*/,
const boost::system::error_code& /*error*/,
std::size_t /*bytes_transferred*/)
{
}
boost::asio::ip::udp::udp::socket socket_;
boost::asio::ip::udp::udp::endpoint remote_endpoint_;
boost::array<char, 1> recv_buffer_;
};
void runUDPServer( CmdLineOpts input )
{
try
{
boost::asio::io_service io_service;
udp_server server(io_service,input.port);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
class udp_client
{
public:
udp_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::udp::udp::endpoint(boost::asio::ip::udp::udp::v4(), 0)) {
boost::asio::ip::udp::udp::resolver resolver(io_service_);
boost::asio::ip::udp::udp::resolver::query query(boost::asio::ip::udp::udp::v4(), host, port);
boost::asio::ip::udp::udp::resolver::iterator iter = resolver.resolve(query);
endpoint_ = *iter;
}
~udp_client()
{
std::cout << "Calling UDP client destructor" << std::endl;
socket_.close();
}
void send() {
socket_.send_to(boost::asio::buffer(send_buf), endpoint_);
}
void recieve_from() {
/*Initialize our endpoint*/
boost::array<unsigned char, 8192> temp;
// boost::asio::buffer boost_buf(temp);
size_t len = socket_.receive_from(
boost::asio::buffer(temp), sender_endpoint);
std::ostringstream ss;
ss << std::hex << std::uppercase << std::setfill( '0' );
std::for_each( temp.cbegin(), temp.cend(), [&]( int c ) { ss << std::setw( 2 ) << c; } );
std::string result = ss.str();
std::cout << "Length of recieved message " << len << std::endl;
std::cout << result << std::endl;
}
private:
boost::asio::io_service& io_service_;
boost::asio::ip::udp::udp::socket socket_;
boost::asio::ip::udp::udp::endpoint endpoint_;
//boost::array<char, 2048> recv_buf;
std::vector<unsigned char> recv_buf;
boost::array<char, 1> send_buf = {{ 0 }};
boost::asio::ip::udp::endpoint sender_endpoint;
};
void runUDPClient(std::string portStr)
{
try
{
boost::asio::io_service io_service;
udp_client client(io_service, "localhost", portStr);
client.send();
client.recieve_from();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
void runClient( CmdLineOpts input )
{
runUDPClient(input.portStr);
}
void runServer( CmdLineOpts input )
{
runUDPServer(input);
}
/**
* Usage: client_server <protocol> <port> <num of packets>
*/
bool clarg_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)> <port>" << std::endl;
result = false;
}
// arg 2: port
int arg2 = std::stoi(argv[3]);
if (arg2 > LOWEST_PORT && arg2 < HIGHEST_PORT )
{
input->port = arg2;
input->portStr = argv[3];
}
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)> <port>" << std::endl;
result = false;
}
}
else
{
std::cout << "Usage: client_server <client (0) or server(1)> <port>" << std::endl;
result = false;
}
return result;
}
int main ( int argc, char *argv[] )
{
CmdLineOpts input;
if (clarg_parse(argc, argv, &input))
{
if(input.servOrClient == 1)
{
runServer(input);
}
else if(input.servOrClient == 0)
{
runClient(input);
}
}
else
{
return 1;
}
return 0;
}
udp_server.hpp
udp_server.hpp
#ifndef UDP_SERVER_H_INCLUDED
#define UDP_SERVER_H_INCLUDED
#include <string>
struct CmdLineOpts
{
std::string portStr;
int port;
int servOrClient;
};
void runUDPServer ( CmdLineOpts input );
bool clarg_parse ( int argc, char *argv[], CmdLineOpts input );
#endif
生成文件
TARGET = udp_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)
我试图修改udp_server.cpp(上述)更改 udp_server :: start_recieve()
函数调用显式地 handle_recieve()',而不必
handle_recieve()注册为回调 async_recieve_from()`。修改后的功能如下
I have tried modifying udp_server.cpp (given above) to change udp_server::start_recieve()
function to explictly call handle_recieve()' instead of having
handle_recieve()registered as a callback to
async_recieve_from()`. The modified function is given below
void udp_server::start_receive()
{
/*m_socket.async_receive_from(
boost::asio::buffer(m_recv_buffer), m_remote_endpoint,
boost::bind(&udp_server::handle_receive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));*/
handle_recieve(boost::system::error_code &error, std::size_t bytes_transferred);
}
不过,上述变化是给我下面的错误。
But the above change is giving me the following error.
g++ -std=c++11 -g -Wall -pedantic -c udp_server.cpp -o udp_server.o
udp_server.cpp: In member function ‘void udp_server::start_receive()’:
udp_server.cpp:22:46: error: expected primary-expression before ‘&’ token
handle_recieve(boost::system::error_code &error, std::size_t bytes_transferred);
^
udp_server.cpp:22:47: error: ‘error’ was not declared in this scope
handle_recieve(boost::system::error_code &error, std::size_t bytes_transferred);
我想知道我做错了,如何改变UDP服务器模式/客户端从拉推。
I would like to know what I am doing wrong and how to change the model of udp server/client to push from pull.
推荐答案
更改客户端:
- ,使其循环在接收(展示多个推送)
更改服务器:
- 请不要马上回应
- 在收到假包的存储客户端的远程端点(地址)
- 当你决定你确实有数据推到客户端,只需通过存储端点的列表,并在那个时候发信息
这篇关于UDP客户端断绝从拉动模式转变,推动模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!