C++网络编程详细讲解_第1页
C++网络编程详细讲解_第2页
C++网络编程详细讲解_第3页
C++网络编程详细讲解_第4页
C++网络编程详细讲解_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第C++网络编程详细讲解目录一、网络编程二、库示例练习

一、网络编程

尽管Boost.Asio可以异步处理任何类型的数据,但它主要用于网络编程。这是因为Boost.Asio早在添加额外的I/O对象之前就支持网络功能。网络函数非常适合异步操作,因为通过网络传输数据可能需要很长时间,这意味着确认和错误可能不会像发送或接收数据的函数那样快。

二、库示例

Boost.Asio提供了许多I/O对象来开发网络程序。示例32.5使用类boost::asio::ip::tcp::socket与另一台计算机建立连接。此示例向网络服务器发送HTTP请求以下载主页。

示例32.5。带有boost::asio::ip::tcp::socket的网络客户端

#includeboost/asio/io_service.hpp

#includeboost/asio/write.hpp

#includeboost/asio/buffer.hpp

#includeboost/asio/ip/tcp.hpp

#includearray

#includestring

#includeiostream

usingnamespaceboost::asio;

usingnamespaceboost::asio::ip;

io_serviceioservice;

tcp::resolverresolv{ioservice};

tcp::sockettcp_socket{ioservice};

std::arraychar,4096bytes;

voidread_handler(constboost::system::error_codeec,

std::size_tbytes_transferred)

if(!ec)

std::cout.write(bytes.data(),bytes_transferred);

tcp_socket.async_read_some(buffer(bytes),read_handler);

voidconnect_handler(constboost::system::error_codeec)

if(!ec)

std::stringr=

"GET/HTTP/1.1\r\nHost:\r\n\r\n";

write(tcp_socket,buffer(r));

tcp_socket.async_read_some(buffer(bytes),read_handler);

voidresolve_handler(constboost::system::error_codeec,

tcp::resolver::iteratorit)

if(!ec)

tcp_socket.async_connect(*it,connect_handler);

intmain()

tcp::resolver::queryq{"","80"};

resolv.async_resolve(q,resolve_handler);

ioservice.run();

}

Example32.5

示例32.5使用了三个处理程序:connect_handler()和read_handler()在建立连接并接收到数据时被调用。resolve_handler()用于名称解析。

因为只有在建立连接之后才能接收数据,并且因为只有在解析名称之后才能建立连接,所以各种异步操作都是在处理程序中启动的。在resolve_handler()中,指向从名称解析的端点的迭代器it与tcp_socket一起用于建立连接。在connect_handler()中,访问tcp_socket以发送HTTP请求并开始接收数据。由于所有操作都是异步的,处理程序被传递给各自的函数。根据操作,可能需要传递其他参数。例如,迭代器它指的是从名称解析的端点。数组字节用于存储接收到的数据。

在main()中,boost::asio::ip::tcp::resolver::query被实例化以创建对象q。q表示对名称解析器的查询,一个类型为boost::asio::ip::tcp::resolver的I/O对象。通过将q传递给async_resolve(),启动异步操作来解析名称。示例32.5解析名称。异步操作启动后,在I/O服务对象上调用run()以将控制权传递给操作系统。

解析名称后,将调用resolve_handler()。处理程序首先检查名称解析是否成功。在这种情况下,ec为0。只有这样才能访问套接字以建立连接。要连接的服务器地址由第二个参数提供,其类型为boost::asio::ip::tcp::resolver::iterator。该参数是名称解析的结果。

对async_connect()的调用之后是对处理程序connect_handler()的调用。再次首先检查ec以确定是否可以建立连接。如果是这样,则在套接字上调用async_read_some()。通过此调用,开始读取数据。接收到的数据存储在数组字节中,作为第一个参数传递给async_read_some()。

当接收到一个或多个字节并将其复制到字节时调用read_handler()。std::size_t类型的参数bytes_transferred包含已接收的字节数。像往常一样,处理程序应该首先检查异步操作是否成功完成。只有在这种情况下,才会将数据写入标准输出。

请注意,在将数据写入std::cout后,read_handler()会再次调用async_read_some()。这是必需的,因为您无法确定整个主页是否已在单个异步操作中下载并复制到字节中。对async_read_some()的重复调用和对read_handler()的重复调用仅在连接关闭时结束,这发生在网络服务器发送整个主页时。然后read_handler()在ec中报告错误。此时,不会向std::cout写入更多数据,并且不会在套接字上调用async_read()。因为没有挂起的异步操作,程序退出。

示例32.6。具有boost::asio::ip::tcp::acceptor的时间服务器

#includeboost/asio/io_service.hpp

#includeboost/asio/write.hpp

#includeboost/asio/buffer.hpp

#includeboost/asio/ip/tcp.hpp

#includestring

#includectime

usingnamespaceboost::asio;

usingnamespaceboost::asio::ip;

io_serviceioservice;

tcp::endpointtcp_endpoint{tcp::v4(),2014};

tcp::acceptortcp_acceptor{ioservice,tcp_endpoint};

tcp::sockettcp_socket{ioservice};

std::stringdata;

voidwrite_handler(constboost::system::error_codeec,

std::size_tbytes_transferred)

if(!ec)

tcp_socket.shutdown(tcp::socket::shutdown_send);

voidaccept_handler(constboost::system::error_codeec)

if(!ec)

std::time_tnow=std::time(nullptr);

data=std::ctime(now);

async_write(tcp_socket,buffer(data),write_handler);

intmain()

tcp_acceptor.listen();

tcp_acceptor.async_accept(tcp_socket,accept_handler);

ioservice.run();

}

Example32.6

示例32.6是一个时间服务器。您可以连接telnet客户端以获取当前时间。之后时间服务器关闭。

时间服务器使用I/O对象boost::asio::ip::tcp::acceptor来接受来自另一个程序的传入连接。您必须初始化对象,以便它知道在哪个端口上使用哪个协议。在示例中,boost::asio::ip::tcp::endpoint类型的变量tcp_endpoint用于告诉tcp_acceptor在端口2014上接受Internet协议版本4的传入连接。

接收器初始化后,调用listen()使接收器开始监听。然后调用async_accept()以接受第一次连接尝试。必须将套接字作为第一个参数传递给async_accept(),该参数将用于在新连接上发送和接收数据。

一旦另一个程序建立连接,就会调用accept_handler()。如果连接建立成功,当前时间会通过boost::asio::async_write()发送。此函数将data中的所有数据写入套接字。boost::asio::ip::tcp::socket还提供了成员函数async_write_some()。此函数在至少发送一个字节时调用处理程序。然后处理程序必须检查发送了多少字节以及还需要发送多少字节。然后,它必须再次调用async_write_some()。使用boost::asio::async_write()可以避免重复计算要发送的字节数和调用async_write_some()。使用此函数开始的异步操作仅在数据中的所有字节都发送完毕后才完成。

发送数据后,会调用write_handler()。该函数使用参数boost::asio::ip::tcp::socket::shutdown_send调用shutdown(),表示程序已完成通过套接字发送数据。由于没有待处理的异步操作,示例32.6退出。请注意,虽然data仅在accept_handler()中使用,但它不能是局部变量。数据通过boost::asio::buffer()引用传递到boost::asio::async_write()。当boost::asio::async_write()和accept_handler()返回时,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论