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. 谷歌最新开源BundleTrack: 无需任何CAD模型的6D物体姿态跟踪算法
  2. JaveWeb中实现分页的总结
  3. 第39级台阶(暴力搜索)
  4. opencv计算物体姿态旋转_物体的三维识别与6D位姿估计:PPF系列论文介绍(五)...
  5. vue——单文件组件
  6. 基于Openstack的企业级实例在360的落地实战
  7. Android 使用fastboot烧录镜像
  8. iphone app开发实战很重要:《iPhone App开发实战手册》读后感
  9. Clickhouse除数为0
  10. EXCEL常用函数公式和VBA汇总
  11. 星星之火-38:20M的LTE带宽,为什么是1200个子载波?
  12. 第二周 自然语言处理与词嵌入(Natural Language Processing and Word Embeddings)
  13. 系列学习分布式任务调度 XXL-JOB 之第 1 篇 —— XXL-JOB 介绍(调度中心、执行器)
  14. mysql pxc搭建_MySQL PXC 高可用集群搭建
  15. python进制转化器(任意进制)
  16. Excel记录指定文件夹下的所有文件名;批量解压压缩包,处理压缩包套压缩包问题;
  17. 80年来最强龙卷风袭击古巴首都 致4死195伤
  18. php程序员职业规划书范文,计算机专业职业生涯规划书
  19. 【HTML——酷炫烟花】(效果+代码)
  20. java 获取wifi强度_Android如何获得wifi信号强度和连接子类型

热门文章

  1. Oracle数据库之SQL单行函数---字符函数之TRIM
  2. linux hal 结构图
  3. 百度地图在vue中使用
  4. 「开源资讯」浏览器中可以深度学习的框架Paddle.js 1.0 发布
  5. java基本数据类型_资深大厂Java程序员,由浅入深Java学习资料,高清视频
  6. Gogs clone仓库地址为localhost
  7. Matlab系列教程_数值计算_求和(积)_求累加(积)
  8. MAC:使用install_name_rpath修改编译结果的rpath
  9. gpg: verify signatures failed: 文件打开错误
  10. hg更新下载指定版本