1.3创建一个主动套接字

来源:互联网 发布:linux awk 分隔符 编辑:程序博客网 时间:2024/06/05 11:33

1.3创建一个主动套接字

​ TCP/IP标准没有告诉我们关于套接字的任何信息。此外,TCP/IP标准几乎没有告诉我们如何实现TCP或UDP协议软件API。通过协议软件API,应用程序可以“享受”这个软件功能。

​ 如果我们观察描述TCP协议的RFC文档#793的第3.8节“接口”, 我们会发现,它仅仅包含TCP协议软件API必须提供的、满足最小功能需求集的函数。协议软件的开发人员完全控制API的所有其他方面,例如API的结构,API包含的函数的名称,对象模型,涉及的抽象概念,附加的辅助功能等等。TCP协议软件的每个开发人员都可以自由选择其实现协议的接口。

​ UDP协议同样适用上述概念:只有一小部分必须(强制)提供的功能在RFC 768描述中被专门介绍。API的开发者拥有对UDP协议软件API的所有其他方面的控制权。

​ 如本章之前介绍中所提到的,Berkeley Sockets API是最流行的TCP和UDP协议API。它围绕套接字——一个代表通信会话环境的抽象对象——的概念进行设计。 在我们可以执行任何网络I/O操作之前,我们必须首先分配一个套接字对象,然后将每个I/O操作与它相关联。

​ Boost.Asio借鉴了Berkeley Sockets API中的许多概念,故而它与Berkeley Sockets API 非常类似。我们可以称Boost.Asio为“面向对象的Berkeley Sockets API”。Boost.Asio库包括一个表示套接字概念的类,它提供了类似于Berkeley Sockets API中的接口方法。

​ 存在两种类型的套接字,旨在向远程应用程序发送数据和从远程应用程序接受数据,或发起连接建立过程的套接字称为主动套接字;被动套接字是用于被动等待来自远程应用程序传入连接请求的套接字, 被动套接字不参与用户数据传输。本章稍后,我们将会介绍被动套接字。

​ 这个方法说明如何创建和打开主动套接字。

How to do it…

​ 以下算法描述了在客户端应用程序中创建和打开主动套接字所需执行的步骤:

  • 创建一个asio :: io_service类的实例,或者使用之前创建的一个该类的实例。
  • 创建一个表示传输层协议(TCP或UDP)和底层IP协议版本(IPv4或IPv6)的类的对象,套接字将使用这些协议进行通信。
  • 创建一个对象表示与所需协议对应的套接字,将asio :: io_service类的对象传递给socket的构造函数。
  • 调用socket的open()方法,将步骤2中创建的表示协议的对象作为参数传递给该方法。

​ 以下代码示例说明了算法的可能实现,假设将通过使用TCP协议和IPv4作为底层协议的套接字进行通信:

#include <boost/asio.hpp>#include <iostream>using namespace boost;int main(){    //步骤1. socket构造函数需要一个“io_service”类的实例。    asio::io_service ios;    //步骤2.创建一个表示TCP协议的tcp类的对象,其中IPv4为底层协议。    asio::ip::tcp protocol = asio::ip::tcp::v4();    //步骤3.实例化一个主动的TCP套接字对象。    asio::ip::tcp::socket sock(ios);    boost::system::error_code ec;    //步骤4.打开套接字。    sock.open(protocol, ec);    if (ec.value() != 0)    {        std::cout << "Failed to open the socket! Error code =" << ec.value() << ". Message: " << ec.message();        return ec.value();    }    return 0;}

How it works…

​ 在第1步中,我们实例化了一个asio :: io_service类的对象。这个类是Boost.Asio I/O功能的核心组件,它提供对底层操作系统的网络I/O服务的访问。Boost.Asio套接字通过这个类对象访问这些服务。因此,所有套接字类构造函数都需要一个asio :: io_service对象作为参数。我们将在后面章节中详细地介绍asio :: io_service类的更多细节。

​ 在下一步中,我们创建一个asio :: ip :: tcp类的实例,这个类表示TCP协议。它不提供功能,更像是包含一组描述协议的值的数据结构。

​ asio :: ip :: tcp类没有public构造函数,相反,它提供了两种静态方法:asio :: ip :: tcp :: v4()和asio :: ip :: tcp :: v6(),它们分别返回标识底层IPv4或IPv6的TCP协议的asio :: ip :: tcp类对象。

​ 此外,asio :: ip :: tcp类包含一些用于TCP协议的基本类型的声明。 其中包括asio :: tcp :: endpoint,asio :: tcp :: socket,asio :: tcp :: acceptor等。 我们看看这些声明在boost/asio/ip/tcp.hpp文件如何表示:

namespace boost {namespace asio {namespace ip { // ... class tcp { public:/// TCP端点的类型。 typedef basic_endpoint<tcp> endpoint; // ... /// The TCP socket type. typedef basic_stream_socket<tcp> socket; /// The TCP acceptor type. typedef basic_socket_acceptor<tcp> acceptor; // ...

​ 在第3步中,我们创建一个asio :: ip :: tcp :: socket类的实例,并将asio :: io_service类的对象作为参数传递给它的构造函数。请注意,此构造函数不会分配底层操作系统的套接字对象。当我们在第4步中调用open()方法,并将指定协议的对象作为参数传递给它时,才真正的分配了底层操作系统的套接字。

​ 在Boost.Asio中,打开一个套接字意味着它与描述一套参数相关联,这套参数描述一个特定的协议,套接字将通过该协议进行通信。当Boost.Asio的socket对象被提供这些参数时,它具有足够的信息来分配底层操作系统的真实套接字对象。

​ asio :: ip :: tcp :: socket类提供了另一个构造函数,它接受一个协议对象作为参数。此构造函数构造一个socket对象并将其打开。请注意,如果构造失败,构造函数会抛出boost :: system :: system_error类型的异常。下面代码示例说明我们如何合并上一个示例中的步骤3和4操作:

try {    //单步调用第3+4步。 可能会抛出异常    asio::ip::tcp::socket sock(ios, protocol);} catch (boost::system::system_error & e) {    std::cout << "Error occured! Error code = " << e.code()  << ". Message: "<< e.what();}

There’s more…

前面的示例说明了如何创建一个主动套接字,并通过TCP协议进行通信。 这与创建通过UDP协议进行通信的套接字的过程与几乎相同。以下示例说明如何创建主动的UDP套接字。 假设套接字将使用UDP协议与IPv6通信作为底层协议。 代码示例没有提供任何解释,因为它与上一个示例非常相似,因此应该不难理解:

#include <boost/asio.hpp>#include <iostream>using namespace boost;int main(){    //步骤1. socket构造函数需要一个“io_service”类的实例。    asio::io_service ios;    //步骤2.创建一个表示使用IPv6作为底层协议的UDP协议的udp类的对象。    asio::ip::udp protocol = asio::ip::udp::v6();    //步骤3.实例化一个活动的UDP套接字对象。    asio::ip::udp::socket sock(ios);    boost::system::error_code ec;    //步骤4.打开套接字。    sock.open(protocol, ec);    if (ec.value() != 0) {        std::cout << "Failed to open the socket! Error code = "                   << ec.value() << ". Message: " << ec.message();        return ec.value();    }    return 0;}

See also

  • 如其名称所示,创建被动套接字的方法提供了对被动套接字的描述,并展示了其使用方法
  • 连接套接字的方法解释了活动套接字的用处之一,即连接到远程应用程序
原创粉丝点击