C++ Boost asio库网络通信 [同/异步] [大三四八九月实习]
2013-08-15 16:08
681 查看
1 C++ Boost库asio网络通信类核心结构
在C++ Boost库中用于通信的类的层次为boost::asio::ip,所有有关通信的类别都在这个层次之下。asio封装了berkeley socket APIS,使其支持TCP,UDP,ICMP通信协议,提供了一个健壮且易用的网络通信库:boost::asio::ip。
(1)ip:tcp
网络通信TCP部分位于的层次为ip:tcp。类是asio网络通信(TCP)部分主要的类,主要形式是定义了多个应用于TCP通信的typedef的类,用来协作完成网路通信。包括端点类endpoint,套接字类socket,流类iostream、acceptor及resolver等等。Socket类是TCP下的类。
ip::tcp的内部类型socket,acceptor及resolver是ip::tcp的核心类,它们封装了socket的连接、断开和数据收发功能,使用它们很容易编写出socket程序。
<1>socket class
属TCP通信的基本类,调用成员函数connect()可以连接到一个指定的通信端点,成功连接后用local_endpoint()和remote_endpoin()获得连接两端的端点信息,用read_some()和write_some()阻塞读写数据,当操作完成后使用close()函数关闭socket[如果不关闭其析构函数也自动调用close关闭 socket]
<2>acceptor class
acceptor类对应socket API的accept()函数功能,它用于服务器端,在指定的端口号接受连接,必须配合socket类让其对象作为参数才能完成通信。<3>resolver class
resolver类对应socket API的getaddrinfo()系列函数,用于客户端解析网址获得可用的IP地址,解析得到的IP地址可以使用socket对象连接。在实际生活中大多数我们不可能知道socket连接另一端的地址,而只有域名,这个时候就应该使用resolver类来通过域名获得可用的IP。它可以实现与IP地址无关的网址解析。(2)ip:address
ip地址独立于TCP等通信协议,asio库使用ip::address来表示ip地址支持ipv4及ipv6。ip地址再加上一个端口号就构成了一个端点(ip::tcp::endpoint),它的主要用法是通过构造函数创建一个可用于socket通信的的端点对象,端点的地址和端口号可以由address和port获取。
可简要查阅其各IP下类的类摘要。
2 编写socket程序
首先明确使用socket类在C++ boost库内的asio库下的ip::tcp下,所以,它得遵循asio基本程序的结构和流程[vs2010boost库配置 asio程序结构流程]。
步骤
(1)建立控制台程序
用VS2010新建两个控制台程序,一个用于socket程序的服务器端,一个用于socket程序的客户端。配置好boost库环境。明确boost库下各类需要包含的头文件、命名空间及宏。(2)用socket类编写服务端程序
[1]遵循asio程序的结构和流程,首先定义io_service对象io_service io_s; |
ip::tcp::acceptor accpt( io_s, ip::tcp::endpoint( ip::tcp::v4(), 55 ) ); |
ip::tcp::socket ser_socket( io_s ); |
accpt.accept( ser_socket ); |
与客户端连上之后,可以用本地socket对象调用remote_endpoint().address()查看客户端的ip地址信息。
[5]向客户端传送数据[如果要聊天,则可以使用循环来实现,不过对于连接的服务器端与客户端可能会断开,所以呢,要做一个完善的网络编程还得随时检测两者的连接是否断开 ]
此数据可以是用户程序内定也可以由交互式的用户输入。
string input_str; cout << "Input your words what you want to say to client:"; cin >> input_str; //Send message to client ser_socket.write_some( buffer( input_str ) ); |
[6]接受客户端发送的数据并显示[ ^-^,高级的以后再说 ]
deadline_timer d_t( io_s, posix_time::seconds(2) ); vector<char> str( 100, 0 ); ser_socket.read_some( buffer( str ) ); cout << "client's answer:" << &str[0] << "\n\n"; |
read_some就是读取客户端发送的数据。
(3)用socket类编写客户端
用socket类编写客户端的步骤和代码跟编写服务器端差不多。[1]创建io_service io_s对象
[2]在客户端之上创建socket对象,创建连接的端口,端口值跟服务器端口保持一致,并指明具体的ipv4 ip地址值
ip::tcp::socket client_socket( io_s ); ip::tcp::endpoint client_ep( ip::address::from_string( "127.0.0.1"), 55 ); |
client_socket.connect( client_ep ); |
client_socket.read_some( buffer( str ), e_c ); cout << "\nreceive form" << client_socket.remote_endpoint().address() << ":"; cout << &str[0]<< "\n"; memset( &str[0], 0, str.size() ); cout << "my reply is:>> Slient!\n"; //Send client_socket.write_some( buffer( "您好我现在有事不在,一会儿跟您联系!") ); |
memset的作用是清楚str的内容而不受上次所存内容的影响。
3程序分析和运行结果
(1)实现似聊天的功能
先启动服务器端,服务器端的socket对象被创建,由acccptor对象调用accept函数来等待客户端的连接。稍后启动客户端,客户端的socket对象和端点对象被创建,客户端socket兑现调用connect函数去连接服务器端,如果一切正常就会建立服务器端和客户端的一次连接。在不考虑服务器端客户端之间连接上会意外断开的可能,那么在二者连接后就可以在它们之间实现很多操作(如数据传输)。对于带周期规律性的操作如聊天,就可以采取循环操作来完成。如果只实现程序中描述的聊天模式,那么只需要在服务器端数据传输和数据接收部分加一个条件循环[如while(true)],只需要在客户端数据接收和数据发送部分加一个条件循环[如while( tue ) ]。
(2)程序中的隐患
对于两个程序之间的通信,很可能出现许多的异常,此时为了程序的可调性和对用户的良好性,就应该对各种异常做出回应。最好是使用C++的try-throw-catch机制来解决这个问题。socket类中的函数几乎每个函数都接受一个检测异常的boost::system::error_codee_c;
参数,并会将错误返回给参数e_c。
程序中有以下几个地方存在这样的隐患:
[1]客户端在连接服务器端时,需要判断两者是否真的连接成功。如果不判断程序会继续进行,后面的数据处理就没有意义而且会引发错误。
client_socket.connect( client_ep, e_c ); if( e_c ) { throw boost::system::system_error( e_c ); } |
if ( e_c == boost::asio::error::eof ) { break; } else if ( e_c ) { throw boost::system::system_error( e_c ); } |
(3)程序运行结果
先运行服务器端程序,后运行客户端程序,这样子才能保证客户端能连接上服务器端。[1]运行服务器端,确定已经在等待客户端的连接
图1 运行服务器端
[2]运行客户端,简单的看一下服务器端和客户端的通信
图2 服务器端与客户端的数据通信
被封装的东东就是强大呀,依旧是字符界面的编程,比最开始多需要的东西是C++面向对象的思想和开发环境中环境库的配置。
4.异步方式的网络通信总结
[1]就网络通信方面的步骤跟同步网络通信的步骤一个样一个样的,只是在每要进行异步操作时所调用的函数不同( 多一个async的前缀 ),然后多一个异步的机制。
[2]就同步/异步程序的步骤[ 同步/异步小机制 ]
异步方式就比同步方式多一个回调函数和多调用is_service::run()函数两个步骤。对于回调函数的参数问题可以用bind来解决,对于异步调用函数的生存空间书中所述说可以用智能指针来解决( 回调函数经异步调用后还能够被主程序继续使用 )。
[3]关于如何利用同步/异步方式
这还得归结于对同步/异步运行机制的把握和设计功底了。再加上如果用上多线程,嘿嘿,功能应该就会变得很强大,哪怕是同步机制。只是这种组合会稍微难点,但每个模块( 多线程,同步/异步,网络通信)在程序设计时一般都不会被孤立。
此次笔记记录完毕。
相关文章推荐
- C++ Boost asio库网络通信 [同/异步] 笔记
- C++ boost::asio::serial_port 串口通信类 使用 封装 [大三四八九月实习]
- C++ Boost库 asio同步/异步模式[ 定时器来体现 ] [大三四八九月实习]
- 排列组合中不需要考虑组合数的情形 [大三四八九月实习]
- 异步非阻塞套接字Winsock开发网络通信程序的经典入门
- 网络通信之同步异步阻塞非阻塞
- C++各大有名库的介绍——网络通信
- linux C++ 网络通信 -- Broken pipe,接收端突然断开,发送没收到,仍然发送消息,会导致进程崩溃
- twisted是python实现的基于事件驱动的异步网络通信构架。
- VMWare Debian Linux 图形界面 vmware tools 安装 [大三四八九月实习]
- 跨平台网络通信与服务器框架 acl 3.2.0 发布,acl_cpp 是基于 acl 库的 C++ 库
- 转: 异步非阻塞套接字Winsock开发网络通信程序的经典入门
- 【java面试系列之网络编程】TCP和UDP的区别、TCP协议的三次握手和四次挥手、TCP协议的通信状态、网络编程时的同步、异步、阻塞、非阻塞、进程间的通信方式、TCP的流量控制和拥塞控制
- BOOST TCP 异步 网络通信
- c++ Windows Socket实现最简单的C/S网络通信(TCP)
- C++网络通信框架 ACE
- unity开发:Qt C++与unity之间UDP网络通信
- 实习中的一总结 [大三四八九月实习]
- Winsock的事件I/O异步模型(开发网络通信程序入门的继续)
- 【开源】C++异步网络框架,希望对感兴趣的同学带来一些启发。