zoukankan      html  css  js  c++  java
  • Asio学习1: TCP客户端:对准时间 解析

    #include <iostream>
    #include 
    <boost/array.hpp>
    #include 
    <boost/asio.hpp>
    //本程序的目的是访问一个时间同步服务器,我们需要用户指定一个服务器(如time-a.nist.gov),用IP亦可. 

    using boost::asio::ip::tcp;

    int main(int argc, char* argv[])
    {
      
    try
      
    {
        
    if (argc != 2)
        
    {
          std::cerr 
    << "Usage: client <host>" << std::endl;
          
    return 1;
        }

        
    //用asio进行网络连接至少需要一个boost::asio::io_service对象 
         boost::asio::io_service io_service;

         
    /*
          我们需要把在命令行参数中指定的服务器转换为TCP上的节点.
          完成这项工作需要boost::asio::ip::tcp::resolver对象 
         
    */


        tcp::resolver resolver(io_service);
        
    /*
        一个resolver对象查询一个参数,并将其转换为TCP上节点的列表.
        这里我们把argv[1]中的sever的名字和要查询字串daytime关联. 
        
    */


        tcp::resolver::query query(argv[
    1], "daytime");
        
    /*
        节点列表可以用 boost::asio::ip::tcp::resolver::iterator 来进行迭代.
        iterator默认的构造函数生成一个end iterator. 
        
    */


        tcp::resolver::iterator endpoint_iterator 
    = resolver.resolve(query);
        tcp::resolver::iterator end;
        
    /*
        现在我们建立一个连接的sockert,由于获得节点既有IPv4也有IPv6的.
        所以,我们需要依次尝试他们直到找到一个可以正常工作的.这步使得我们的程序独立于IP版本 
        
    */


        tcp::socket socket(io_service);
        boost::asio::error error 
    = boost::asio::error::host_not_found;
        
    while (error && endpoint_iterator != end)
        
    {
          socket.close();
          socket.connect(
    *endpoint_iterator++, boost::asio::assign_error(error));
        }

        
    if (error)
          
    throw error;
         
    /*
         连接完成,我们需要做的是读取daytime服务器的响应. 
         我们用boost::array来保存得到的数据,boost::asio::buffer()会自动根据array的大小暂停工作,
         来防止缓冲溢出.除了使用boost::array,也可以使用char [] 或std::vector. 
         
    */


        
    for (;;)
        
    {
          boost::array
    <char128> buf;
          boost::asio::error error;

          size_t len 
    = socket.read_some(
              boost::asio::buffer(buf), boost::asio::assign_error(error));
         
    /*
           当服务器关闭连接时,boost::asio::ip::tcp::socket::read_some()会用boost::asio::error::eof标志完成, 
           这时我们应该退出读取循环了. 
          
    */


          
    if (error == boost::asio::error::eof)
            
    break// Connection closed cleanly by peer.
          else if (error)
            
    throw error; // Some other error.

          std::cout.write(buf.data(), len);
        }


      }

      
    catch (std::exception& e)
      
    {
        std::cerr 
    << e.what() << std::endl;
      }

    }

    注:下面这一段如果看起来有点麻烦的话可以写简单些,就让其只解析ipv4类型地址,端口号为13,只连接一次

        tcp::resolver::query query(argv[1], "daytime");
        tcp::resolver::iterator endpoint_iterator 
    = resolver.resolve(query);
        tcp::resolver::iterator end;

        tcp::socket socket(io_service);
        boost::asio::error error 
    = boost::asio::error::host_not_found;
        
    while (error && endpoint_iterator != end)
        
    {
          socket.close();
          socket.connect(
    *endpoint_iterator, boost::asio::assign_error(error));
        }

        
    if (error)
          
    throw error;

    简单点的:

        //域名解析,只将域名解析为ipv4地址
        tcp::resolver::query query(tcp::v4(),argv[1], "13");
        tcp::resolver::iterator endpoint_iterator 
    = resolver.resolve(query);
        
    //只连接一次
        tcp::socket socket(io_service);
        boost::asio::error error 
    = boost::asio::error::host_not_found;    
        socket.connect(
    *endpoint_iterator, boost::asio::assign_error(error));   
        
    if (error)
          throw error;  

    下面是用winsock api(阻塞模式) 所写的代码,可以比较一下

    #include <iostream>
    #include 
    <winsock2.h>
    #pragma comment(lib,"ws2_32.lib")

    int main(int argc, char* argv[])
    {
        
    if(argc<2)
        {
            std::cout 
    << "usage: tcp_datatime hostname(time-a.nist.gov) " << std::endl;
            
    return -1;
        }
        WSADATA wsaData;
        
    if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
        {
            std::cout 
    << " lib error ";
            
    return -1;
        }

        SOCKET cliSocket;
        cliSocket 
    = socket(AF_INET, SOCK_STREAM,0);


        SOCKADDR_IN addr;
        memset(
    &addr,0sizeof(addr));
        addr.sin_port 
    = htons(13);
        addr.sin_family 
    = AF_INET;
        
    if( (addr.sin_addr.s_addr = inet_addr(argv[1])) == INADDR_NONE)
        {
            hostent 
    * hostent;
            hostent  
    = gethostbyname(argv[1]);
            
    if(hostent == NULL)
            {
                std::cout 
    << " can't resolve host! " ;
                
    return -1;
            }
            memcpy(
    &addr.sin_addr,hostent->h_addr_list[0],4);
        }
        
        
    if( connect(cliSocket, (sockaddr*)&addr,sizeof(sockaddr)) != 0)
        {
            std::cout 
    << "connect error ";
            
    return -1;
        }
        
        
    char buf[100];
        
    int recvSize = recv(cliSocket, buf, sizeof(buf), 0);
        buf[recvSize] 
    = 0;
        std::cout 
    << buf << std::endl;
        
    return 0;
    }
  • 相关阅读:
    简单工厂
    Asp.Net Catch的应用
    ADO和ADO.NET的区别
    PLSql语句学习(三)
    三层结构的B/S系统(收藏)
    MVC 模式
    利用.net反射动态调用指定程序集的中的方法
    .NET反射的简单示例
    ToString格式化
    HTML:关于位置的几个概念
  • 原文地址:https://www.cnblogs.com/lzjsky/p/2157329.html
Copyright © 2011-2022 走看看