C++ boost::asio编程-同步TCP详解及实例代码_C 语言

boost::asio编程-同步TCP

boost.asio库是一个跨平台的网络及底层IO的C++编程库,它使用现代C++手法实现了统一的异步调用模型。

boost.asio库支持TCP、UDP、ICMP通信协议。

下面介绍同步TCP模式:

大家好!我是同步方式!

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

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

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

我的介绍就有这里,谢谢大家!

同步方式示例代码:

服务器端

// BoostTcpServer.cpp : 定义控制台应用程序的入口点。
// 

#include "stdafx.h"
#include "boost/asio.hpp"
#include "boost/thread.hpp" 

using namespace std;
using namespace boost::asio; 

#ifdef _MSC_VER
#define _WIN32_WINNT  0X0501 //避免VC下编译警告
#endif 

#define PORT 1000
#define IPV6
//#define IPV4 

int _tmain(int argc, _TCHAR* argv[])
{
  // 所有asio类都需要io_service对象
  io_service iosev; 

  //创建用于接收客户端连接的acceptor对象
#ifdef IPV4
  ip::tcp::acceptor acceptor(iosev,ip::tcp::endpoint(ip::tcp::v4(), PORT));
#endif 

#ifdef IPV6
  ip::tcp::acceptor acceptor(iosev,ip::tcp::endpoint(ip::tcp::v6(), PORT));
#endif 

  while (true)
  {
    // socket对象
    ip::tcp::socket socket(iosev);
    // 等待直到客户端连接进来
    acceptor.accept(socket);
    // 显示连接进来的客户端
    std::cout <<"remote ip:"<<socket.remote_endpoint().address()<<endl;
    std::cout <<"remote port:"<<socket.remote_endpoint().port() << std::endl; 

    char buf[2048];
    boost::system::error_code ec;
    while(1)
    {
      socket.read_some(buffer(buf),ec);
      if (ec)
      {
        std::cout <<boost::system::system_error(ec).what() << std::endl;
        break ;
      }
      std::cout<<"recv msg:"<<buf<<endl;
      if(strcmp(buf,"bye")==0)//收到结束消息结束客户端连接
      {
        break;
      }
      socket.write_some(buffer("I heared you!\n"),ec);
      if (ec)
      {
        std::cout <<boost::system::system_error(ec).what() << std::endl;
        break ;
      }
    }
    socket.close();
    // 与当前客户交互完成后循环继续等待下一客户连接
  }
  return 0;
} 

客户端

// BoostTcpClient.cpp : 定义控制台应用程序的入口点。
// 

#include "stdafx.h"
#include "boost/asio.hpp" 

using namespace boost::asio; 

#ifdef _MSC_VER
#define _WIN32_WINNT  0X0501 //避免VC下编译警告
#endif 

#define PORT 1000
#define IPV6
//#define IPV4 

int _tmain(int argc, _TCHAR* argv[])
{
  // 所有asio类都需要io_service对象
  io_service iosev;
  // socket对象
  ip::tcp::socket socket(iosev); 

  // 连接端点,这里使用了本机连接,可以修改IP地址测试远程连接
#ifdef IPV4
  ip::address_v4 address=ip::address_v4::from_string("127.0.0.1");
#endif 

#ifdef IPV6
  //"0:0:0:0:0:0:0:1"为IPV6的本机回环地址,类似于"127.0.0.1"
  ip::address_v6 address=ip::address_v6::from_string("0:0:0:0:0:0:0:1");
#endif
  ip::tcp::endpoint ep(address, PORT);
  // 连接服务器
  boost::system::error_code ec;
  socket.connect(ep,ec);
  // 如果出错,打印出错信息
  if (ec)
  {
    std::cout << boost::system::system_error(ec).what() << std::endl;
    return -1;
  } 

  //循环发送和接收数据
  for(int i=0;i<5;++i)
  {
    //发送数据
    socket.write_some(buffer("hello"), ec);
    // 接收数据
    char buf[100];
    size_t len=socket.read_some(buffer(buf), ec);
    std::cout.write(buf, len);
    Sleep(500);
  }
  //发送与服务端约定好的结束语,由服务端断链
  socket.write_some(buffer("bye"), ec); 

  getchar();
  return 0;
}

代码中兼容了IPV4和IPV6两种IP协议,使用宏定义选择使用哪种IP协议,当然客户端和服务端的协议必须一致才能正常通信。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索c++
同步TCP
c语言、c语言编程软件、c语言入门经典、c语言入门、c语言教程,以便于您获取更多的相关知识。

时间: 2024-12-09 16:23:18

C++ boost::asio编程-同步TCP详解及实例代码_C 语言的相关文章

C++ boost::asio编程-异步TCP详解及实例代码_C 语言

C++ boost::asio编程-异步TCP 大家好,我是异步方式 和同步方式不同,我从来不花时间去等那些龟速的IO操作,我只是向系统说一声要做什么,然后就可以做其它事去了.如果系统完成了操作, 系统就会通过我之前给它的回调对象来通知我. 在ASIO库中,异步方式的函数或方法名称前面都有"async_ " 前缀,函数参数里会要求放一个回调函数(或仿函数).异步操作执行 后不管有没有完成都会立即返回,这时可以做一些其它事,直到回调函数(或仿函数)被调用,说明异步操作已经完成. 在ASI

C++函数重载详解及实例代码_C 语言

C++函数的重载 定义 在同一个作用域中,函数名相同,函数的参数列表不同的函数之间构成重载关系,在不同作用域中的同名函数遵循标识符隐藏的原则 ATTENTION:重载与函数的返回值类型无关,因为声明一个函数不需要返回类型,所以无法用来区分哪个函数 常函数和普通成员函数之间构成重载,重载时常对象调用常成员函数,一般对象调用一般成员函数 class A{ - public: void getVal()const{-} void getVal(){-} }; int main(){ const A a

C++ 继承详解及实例代码_C 语言

C++继承可以是单一继承或多重继承,每一个继承连接可以是public,protected,private也可以是virtual或non-virtual.然后是各个成员函数选项可以是virtual或non-virtual或pure virtual.本文仅仅作出一些关键点的验证. public继承,例如下: 1 class base 2 {...} 3 class derived:public base 4 {...} 如果这样写,编译器会理解成类型为derived的对象同时也是类型为base的对象

C语言之单向链表详解及实例代码_C 语言

1,单向链简洁. 单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始:链表是使用指针进行构造的列表:又称为结点列表,因为链表是由一个个结点组装起来的:其中每个结点都有指针成员变量指列表中的下一个结点:列表是由结点构成,由head指针指向第一个成为表头的结点而终止于最后一个指向nuLL的指针: 2,例子要求: 根据示例代码中的例子,完成单向链表(single linked list)中的以字符串为数据的链表的插入.删除以及查找,并支持单向链表的反转

C语言 奇偶排序算法详解及实例代码_C 语言

C语言奇偶排序算法 奇偶排序,或奇偶换位排序,或砖排序,是一种相对简单的排序算法,最初发明用于有本地互连的并行计算.这是与冒泡排序特点类似的一种比较排序.该算法中,通过比较数组中相邻的(奇-偶)位置数字对,如果该奇偶对是错误的顺序(第一个大于第二个),则交换.下一步重复该操作,但针对所有的(偶-奇)位置数字对.如此交替进行下去. 使用奇偶排序法对一列随机数字进行排序的过程 处理器数组的排序 在并行计算排序中,每个处理器对应处理一个值,并仅有与左右邻居的本地互连.所有处理器可同时与邻居进行比较.交

C语言 文件操作解析详解及实例代码_C 语言

C语言文件操作解析         在文件操作中除了打开操作以及读写操作,还有几种比较常见的操作.下面介绍一下这些操作中涉及到的函数. 一.移动位置指针的函数    rewind函数和fseek函数,这两个函数的原型是:    void rewind(FILE *fp);     将位置指针移动到文件首   int fseek(FILE *fp,long int offset,int origin);   将位置指针移动到距离origin的offset字节数的位置   其中对于fseek函数中的

C++ 初始化列表详解及实例代码_C 语言

C++ 初始化列表 何谓初始化列表 与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段.在C++中,struct和class的唯一区别是默认的访问性不同,而这里我们不考虑访问性的问题,所以下面的代码都以struct来演示. struct foo { string name ; int id ; foo(string s, int i):name(s), id(i){} ; // 初始化列表 }; 构造函数的两个执行

C语言之双向链表详解及实例代码_C 语言

1,双向链表简介. 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点.一般我们都构造双向循环链表. 2,例子要求: 完成双向链表的插入.删除以及查找,将学生管理系统使用的数组,以双向链表的方式实现,能够支持无限制的学生人数的增删改查以及保存. 3,代码实现. #include <stdio.h> #include <string.h> #include <

C语言 共用体(Union)详解及示例代码_C 语言

通过前面的讲解,我们知道结构体(Struct)是一种构造类型或复杂类型,它可以包含多个类型不同的成员.在C语言中,还有另外一种和结构体非常类似的语法,叫做共用体(Union),它的定义格式为: union 共用体名{     成员列表 }; 共用体有时也被称为联合或者联合体,这也是 Union 这个单词的本意. 结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响:而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员. 结构体占用的内存大于等于所有成员占用的内