/*
* echo server 一种非常简单的服务,它把接收到的数据原封不动地发送给客户
* 所以客户发送什么它就会接收什么
*/
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
//这是一个UDP实现的服务器程序
//这个程序实现体现一个重要的区别:UDP与TCP的区别
//作为无连接的UDP与作为面向连接的TCP,它们使用存在着许多不同点
using boost
::
asio
::
ip
::
udp
;
class server
{
public
:
server
(boost
::
asio
::
io_service
& io_service,
short port
)
: io_service_
(io_service
),
socket_
(io_service, udp
::
endpoint
(udp
::
v4
(
), port
)
)
{
//由于UDP是无连接的,所以我没有必要在那个地方等客户连接
//相反我们只是在那里等着客户发送过来的数据,如果我们从一个地方收到一个数据
//并且我们要回复这个消息,此时很简单,从哪儿来的数据,消息就回复到哪儿
//async_receive_from 函数中的那个参数sender_endpoint就是为了这个目的,其它并不是一个输入性的函数
//相反它是输出性的参数,async_receiv_from函数把数据据来源地放于这个参数中,
//如下我们回复的时候就可以使用了。
socket_.
async_receive_from
(
boost
::
asio
::
buffer
(data_, max_length
), sender_endpoint_,
boost
::
bind
(
&server
::
handle_receive_from,
this,
boost
::
asio
::
placeholders
::
error,
boost
::
asio
::
placeholders
::
bytes_transferred
)
)
;
}
void handle_receive_from
(
const boost
::
system
::
error_code
& error,
size_t bytes_recvd
)
{
if
(
!error
&& bytes_recvd
>
0
)
{
//此时我们回复,回复到sender_endpiont,上次调用async_recive_from
//会把来源地放到这里,asio的文档要求用户需要保证这个sender_endpiont
//在上次调用之后一直到此都不有效的,本示例把它放在类型的定义中,所以
//会一直有效
socket_.
async_send_to
(
boost
::
asio
::
buffer
(data_, bytes_recvd
), sender_endpoint_,
boost
::
bind
(
&server
::
handle_send_to,
this,
boost
::
asio
::
placeholders
::
error,
boost
::
asio
::
placeholders
::
bytes_transferred
)
)
;
}
else
{
socket_.
async_receive_from
(
boost
::
asio
::
buffer
(data_, max_length
), sender_endpoint_,
boost
::
bind
(
&server
::
handle_receive_from,
this,
boost
::
asio
::
placeholders
::
error,
boost
::
asio
::
placeholders
::
bytes_transferred
)
)
;
}
}
void handle_send_to
(
const boost
::
system
::
error_code
&
/*error*/,
size_t
/*bytes_sent*/
)
{
//接收之后发送,发送之后再接收,这是由应用类型定义的,所以
//从某种意义上与asio没有关系
socket_.
async_receive_from
(
boost
::
asio
::
buffer
(data_, max_length
), sender_endpoint_,
boost
::
bind
(
&server
::
handle_receive_from,
this,
boost
::
asio
::
placeholders
::
error,
boost
::
asio
::
placeholders
::
bytes_transferred
)
)
;
}
private
:
boost
::
asio
::
io_service
& io_service_
;
udp
::
socket socket_
;
udp
::
endpoint sender_endpoint_
;
enum
{ max_length
= 1024
}
;
char data_
[max_length
]
;
}
;
int main
(
int argc,
char
* argv
[
]
)
{
try
{
if
(argc
!
= 2
)
{
std
::
cerr
<<
"Usage: async_udp_echo_server <port>\n"
;
return
1
;
}
boost
::
asio
::
io_service io_service
;
using
namespace std
;
// For atoi.
server s
(io_service,
atoi
(argv
[1
]
)
)
;
io_service.
run
(
)
;
}
catch
(std
::
exception
& e
)
{
std
::
cerr
<<
"Exception: "
<< e.
what
(
)
<<
"\n"
;
}
return
0
;
}