首頁 >後端開發 >C#.Net教程 >C++ boost::asio程式設計-同步TCP詳解及實例程式碼

C++ boost::asio程式設計-同步TCP詳解及實例程式碼

黄舟
黄舟原創
2016-12-14 17:01:461790瀏覽

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和IPV666 月使用程式碼和服務端的協定必須一致才能正常通訊。

感謝閱讀,希望能幫助大家,更多相關文章請關注PHP中文網(www.php.cn) !


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn