1. 同步和异步

网络编程分为同步模式和异步模式:
同步模式是有一个数据块客户端发送过来,服务端就必须处理完才能处理下一个数据块;
异步模式是客户端发送的数据块放入缓存队列;
异步处理不阻塞,同步模式是阻塞式的。

2. 编程实例

2.1 同步模式

同步模式介绍
大家好!我是同步方式!

我的主要特点就是执着!所有的操作都要完成或出错才会返回,不过偶的执着被大家称之为阻塞,实在是郁闷~~(场下一片嘘声),其实这样也是有好处的,比如逻辑清晰,编程比较容易。

在服务器端,我会做个socket交给acceptor对象,让它一直等客户端连进来,连上以后再通过这个socket与客户端通信, 而所有的通信都是以阻塞方式进行的,读完或写完才会返回。

在客户端也一样,这时我会拿着socket去连接服务器,当然也是连上或出错了才返回,最后也是以阻塞的方式和服务器通信。

有人认为同步方式没有异步方式高效,其实这是片面的理解。在单线程的情况下可能确实如此,我不能利用耗时的网络操作这段时间做别的事情,不是好的统筹方法。不过这个问题可以通过多线程来避免,比如在服务器端让其中一个线程负责等待客户端连接,连接进来后把socket交给另外的线程去和客户端通信,这样与一个客户端通信的同时也能接受其它客户端的连接,主线程也完全被解放了出来。

同步模式编程
服务器端

#include "stdafx.h"
#include<boost/asio.hpp>
#include<iostream>
#include<boost/thread.hpp>
#include<boost/bind.hpp>
using namespace std;//流程:
//① 创建io_service对象
//② 打包IP和端口
//③ 利用ios和ep创建连接器
//④ 利用io_service对象创建socket
//⑤ 利用连接器连接
//⑥ 读写信息int _tmain(int argc, _TCHAR* argv[])
{boost::asio::io_service ios;//asio网络编程必须io_service对象boost::asio::ip::tcp::endpoint ep(boost::asio::ip::tcp::v4(),12248);//打包IP和端口boost::asio::ip::tcp::acceptor ac(ios,ep);//利用ios和ep创建连接器while (true)//监听客户端{boost::asio::ip::tcp::socket sock(ios);//利用io_service对象创建socketac.accept(sock);//连接客户端的socket//接收客户端消息,如果没有接收到,就一直卡在这里cout << sock.remote_endpoint().address() << endl;//显示连接进来的客户端信息boost::system::error_code ec;if (ec){cout << boost::system::system_error(ec).what() << endl;break;}else{sock.write_some(boost::asio::buffer("hello world!"), ec);}}return 0;
}

补充说明:
服务器端,做个socket交给acceptor对象,让它一直等客户端连进来,连上以后再通过这个socket与客户端通信。如果一直连不上,就卡在这里。

客户端

#include "stdafx.h"
#include<iostream>
#include<boost/asio.hpp>
#include<boost/array.hpp>
using namespace std;int _tmain(int argc, _TCHAR* argv[])
{try{boost::asio::io_service ios;//asio网络编程必须io_service对象boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"),12248);//打包IP和端口boost::asio::ip::tcp::socket sock(ios);//创建socketsock.connect(ep);//利用IP和端口连接服务器while (true){boost::array<char, 128> buf;boost::system::error_code ec;size_t len = sock.read_some(boost::asio::buffer(buf),ec);if (ec == boost::asio::error::eof)break;else if (ec)throw boost::system::system_error(ec);cout.write(buf.data(),len);}}catch (exception &e){cout << e.what() << endl;}return 0;
}

此外,在同步模式下,可以通过多线程来避免阻塞。在服务器端让其中一个线程负责等待客户端连接,连接进来后把socket交给另外的线程去和客户端通信,这样与一个客户端通信的同时也能接受其它客户端的连接,主线程也完全被解放了出来。示例如下:

//服务器端
boost::asio::io_service ios;
//asio编程必须io_service对象,服务端和客户端创建socket和服务端创建acceptor对象要用boost::asio::ip::tcp::endpoint ep(boost::asio::ip::tcp::v4(),9800);
//TCP协议的服务器所在的IP和网络编程开放的端口,客户端连接的IP和端口boost::asio::ip::tcp::acceptor acceptor(ios,ep);//监听连接
while(1)
{boost::asio::ip::tcp::socket sock(ios);//创建socket连接对象acceptor.accept(sock);cont<<sock.remote_endpoint().address()<<endl;boost::thread(boost::bind(svr_handle,sock)).detach();
}//交互处理
void svr_handle(boost::asio::ip::tcp::socket sock)
{string msg;sock.write_some(boost::asio::buffer("hello world"));char msg[1024];sock.read_some(boost::asio::buffer(msg));cout<<"client send msg:"<<msg<<endl;}

2.2 异步模式

和同步方式不同,异步方式从来不花时间去等那些龟速的IO操作,我只是向系统说一声要做什么,然后就可以做其它事去了。如果系统完成了操作, 系统就会通过我之前给它的回调对象来通知我。
在ASIO库中,异步方式的函数或方法名称前面都有“async_ ” 前缀,函数参数里会要求放一个回调函数。异步操作执行后不管有没有完成都会立即返回,这时可以做一些其它事,直到回调函数被调用,说明异步操作已经完成。
在ASIO中很多回调函数都只接受一个boost::system::error_code参数,在实际使用时肯定是不够的,所以一般使用仿函数携带一堆相关数据作为回调,或者使用boost::bind来绑定一堆数据。
另外要注意的是,只有io_service类的run()方法运行之后回调对象才会被调用,否则即使系统已经完成了异步操作也不会有任 务动作。

服务端

#include "stdafx.h"
#include<boost/asio.hpp>
#include<boost/shared_ptr.hpp>
#include<boost/thread.hpp>
#include<iostream>
using namespace std;class AsyncServer
{public://构造函数AsyncServer(boost::asio::io_service &io, boost::asio::ip::tcp::endpoint &ep) :ios(io), ac(io,ep){this->start();}private:boost::asio::io_service &ios;boost::asio::ip::tcp::acceptor ac;typedef boost::shared_ptr<boost::asio::ip::tcp::socket> sock_ptr;//启动异步连接,接受客户端的连接请求void start(){sock_ptr sock(new boost::asio::ip::tcp::socket(ios));ac.async_accept(*sock, boost::bind(&AsyncServer::accept_handler, this, boost::asio::placeholders::error, sock));}void accept_handler(const boost::system::error_code &ec, sock_ptr &sock){if (ec)return;cout << "客户端地址" << sock->remote_endpoint().address() << endl;cout << "客户端端口" << sock->remote_endpoint().port() << endl;//异步模式向客户端发送数据,发送完成时调用write_handersock->async_write_some(boost::asio::buffer("Hello World"),boost::bind(&AsyncServer::write_handler,this,boost::asio::placeholders::error));//再次启动异步接受连接start();}void write_handler(const boost::system::error_code &){cout << "服务端发送消息完成" << endl;}};int _tmain(int argc, _TCHAR* argv[])
{try{boost::asio::io_service ios;boost::asio::ip::tcp::endpoint ep(boost::asio::ip::tcp::v4(),12248);AsyncServer server(ios,ep);//启动异步服务ios.run();}catch (exception &e){cout << e.what() << endl;}return 0;
}

客户端

#include "stdafx.h"
#include<iostream>
#include<boost/asio.hpp>
#include<boost/array.hpp>
#include<boost/bind.hpp>
#include<boost/asio/buffer.hpp>
using namespace std;class AsyncClient
{public:AsyncClient(boost::asio::io_service &io, boost::asio::ip::tcp::endpoint ep):ios(io),ep(ep){this->start();}private:boost::asio::io_service &ios;typedef boost::shared_ptr<boost::asio::ip::tcp::socket> sock_ptr;boost::asio::ip::tcp::endpoint ep;char m_RcvStr[1024];void start(){sock_ptr sock(new boost::asio::ip::tcp::socket(ios));sock->async_connect(ep, boost::bind(&AsyncClient::connect_handler, this, boost::asio::placeholders::error, sock));}void connect_handler(const boost::system::error_code &ec, sock_ptr &sock){if (ec)return;cout << "服务端地址" << sock->remote_endpoint().address() << endl;cout << "服务端端口" << sock->remote_endpoint().port() << endl;//异步模式向客户端发送数据,发送完成时调用write_handersock->async_read_some(boost::asio::buffer(m_RcvStr), boost::bind(&AsyncClient::read_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));}void read_handler(const boost::system::error_code &ec,size_t i){if (ec)return;cout << "读数据成功" << endl;cout << m_RcvStr << endl;cout << i<<endl;}
};int _tmain(int argc, _TCHAR* argv[])
{try{boost::asio::io_service ios;boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 12248);AsyncClient client(ios,ep);ios.run();}catch (exception &e){cout << e.what() << endl;}   return 0;
}

3. 补充说明

3.1 io_serveice类不支持拷贝构造

如下程序:

class A
{private:io_service io;
public:A(io_service io_): io(io_){}
};

程序执行时,会报错;原因在于没有使用引用,而是使用了拷贝。
应该修改成:

io_service &io;

BOOST库介绍(三)——网络编程相关的库相关推荐

  1. Linux网络编程 | 信号 :信号函数、信号集、统一事件源 、网络编程相关信号

    文章目录 信号函数 信号集 统一事件源 网络编程相关信号 Linux 进程信号:信号的概念.生命周期.产生流程.阻塞 在半年前我写过一篇博客介绍了Linux中信号的概念以及处理流程,这次再来深入的讲一 ...

  2. 90分钟详解网络编程相关的细节处理丨 reactor丨网络io丨epoll丨C/C++丨Linux服务器开发丨后端开发丨Linux后台开发

    90分钟搞懂网络编程相关细节处理 1. 网络编程四要素 2. io多路复用 3. reactor三种基础封装方式 视频讲解如下,点击观看: 90分钟详解网络编程相关的细节处理丨 reactor丨网络i ...

  3. 二十七、GIL及网络编程相关知识

    网络编程相关 一 GIL全局解释器锁 二 GIL与普通互斥锁的区别 三 多线程与多进程区别 3.1 单核 3.2 多核 3.3 代码验证 四 死锁 五 信号量 六 Event事件 七 进程池与线程池 ...

  4. linux 网络编程相关知识

    1:tcp和udp的区别 2:流量控制和拥塞控制的实现机制 3:滑动窗口的实现机制 4:多线程如何同步. 5:进程间通讯的方式有哪些,各有什么优缺点 6:tcp连接建立的时候3次握手的具体过程,以及其 ...

  5. linux服务器开发三(网络编程)

    转载自:http://www.cnblogs.com/zfc2201/archive/2017/05/04/6804990.html 作者:水之原 网络基础 协议的概念 什么是协议 从应用的角度出发, ...

  6. java io 网络编程_[笔面] Java IO和网络编程相关面试

    1.网络编程时的同步.异步.阻塞.非阻塞? 同步:函数调用在没得到结果之前,没有调用结果,不返回任何结果. 异步:函数调用在没得到结果之前,没有调用结果,返回状态信息. 阻塞:函数调用在没得到结果之前 ...

  7. Java三:网络编程 视频来源:https://www.bilibili.com/video/BV1LJ411z7vY

    一.网络编程 1.概述 (1)什么是计算机网络:将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息 ...

  8. python 协程库_python --- 协程编程(第三方库gevent的使用)

    1. 什么是协程? 协程(coroutine),又称微线程.协程不是线程也不是进程,它的上下文关系切换不是由CPU控制,一个协程由当前任务切换到其他任务由当前任务来控制.一个线程可以包含多个协程,对于 ...

  9. python编程基础题库_大学moocPython编程基础题库及答案

    参考答案如下 大学间接赞扬的方式可能受到意想不到的效果.() 编程郑玄对"一人贪戾"的"戾"的解释为(),形容在欲望的追寻中出现的人与人的矛盾状态. 郑谷有&l ...

  10. 网络编程相关概念学习笔记

    C/S架构和B/S架构 C/S 架构 C/S 架构是一种典型的两层架构,其全程是Client/Server,即客户端服务器端架构,其客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种 ...

最新文章

  1. 最大元最小元上确界_托盘天平最大秤量和最小秤量
  2. python中处理日期和时间的标准模块是-Python time模块参考手册
  3. 3.23andorid多语言支持--系统架构
  4. Matlab中disp、fprintf和sprintf
  5. Spring Boot 核心注解与配置文件
  6. LeetCode 890. 查找和替换模式(哈希表)
  7. laravel-admin 在指定的相册下添加照片
  8. 图解数字签名Digital Signature 和数字证书Public-key certificate
  9. 计算机应用技术爱岗敬业,高职专业人才培养方案(计算机应用技术).doc
  10. android tv webview,Android TV开发---WebView焦点处理
  11. Git服务器的搭建和使用
  12. idea风格ui java_IDEA主题美化
  13. 永中云编辑(java版)
  14. ATeam社区(牛客网项目第七章)
  15. 在线负数分数计算机,负分数
  16. 渗透测试之信息搜集总结
  17. 计算机毕业设计之java+ssm生鲜超市进销存管理系统
  18. 台式计算机开机黑屏,联想台式电脑开机黑屏出现英文字母,怎么办?
  19. PJ331 PJ501超小型封装PFM DC/DC升压稳压器
  20. 如何一键解决图片无损放大

热门文章

  1. pure-ftpd 配置
  2. a blog about grid stytem
  3. windows 2003活动目录更名操作[图]
  4. 微信小程序picker中的rang 和rang-key
  5. SpringBoot中级篇-事务@Transactional注解无效
  6. JavaWeb初级篇-HttpPost使用教程
  7. 月考分析五年级英语html,第一学期五年级英语期末考试试卷分析
  8. sw如何缩放装配体_社团内训 | SW从入门到精通
  9. echarts中国地图下钻到区
  10. input输入框计算总和