C++網(wǎng)絡(luò)編程詳細講解_第1頁
C++網(wǎng)絡(luò)編程詳細講解_第2頁
C++網(wǎng)絡(luò)編程詳細講解_第3頁
C++網(wǎng)絡(luò)編程詳細講解_第4頁
C++網(wǎng)絡(luò)編程詳細講解_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第C++網(wǎng)絡(luò)編程詳細講解目錄一、網(wǎng)絡(luò)編程二、庫示例練習(xí)

一、網(wǎng)絡(luò)編程

盡管Boost.Asio可以異步處理任何類型的數(shù)據(jù),但它主要用于網(wǎng)絡(luò)編程。這是因為Boost.Asio早在添加額外的I/O對象之前就支持網(wǎng)絡(luò)功能。網(wǎng)絡(luò)函數(shù)非常適合異步操作,因為通過網(wǎng)絡(luò)傳輸數(shù)據(jù)可能需要很長時間,這意味著確認和錯誤可能不會像發(fā)送或接收數(shù)據(jù)的函數(shù)那樣快。

二、庫示例

Boost.Asio提供了許多I/O對象來開發(fā)網(wǎng)絡(luò)程序。示例32.5使用類boost::asio::ip::tcp::socket與另一臺計算機建立連接。此示例向網(wǎng)絡(luò)服務(wù)器發(fā)送HTTP請求以下載主頁。

示例32.5。帶有boost::asio::ip::tcp::socket的網(wǎng)絡(luò)客戶端

#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()在建立連接并接收到數(shù)據(jù)時被調(diào)用。resolve_handler()用于名稱解析。

因為只有在建立連接之后才能接收數(shù)據(jù),并且因為只有在解析名稱之后才能建立連接,所以各種異步操作都是在處理程序中啟動的。在resolve_handler()中,指向從名稱解析的端點的迭代器it與tcp_socket一起用于建立連接。在connect_handler()中,訪問tcp_socket以發(fā)送HTTP請求并開始接收數(shù)據(jù)。由于所有操作都是異步的,處理程序被傳遞給各自的函數(shù)。根據(jù)操作,可能需要傳遞其他參數(shù)。例如,迭代器它指的是從名稱解析的端點。數(shù)組字節(jié)用于存儲接收到的數(shù)據(jù)。

在main()中,boost::asio::ip::tcp::resolver::query被實例化以創(chuàng)建對象q。q表示對名稱解析器的查詢,一個類型為boost::asio::ip::tcp::resolver的I/O對象。通過將q傳遞給async_resolve(),啟動異步操作來解析名稱。示例32.5解析名稱。異步操作啟動后,在I/O服務(wù)對象上調(diào)用run()以將控制權(quán)傳遞給操作系統(tǒng)。

解析名稱后,將調(diào)用resolve_handler()。處理程序首先檢查名稱解析是否成功。在這種情況下,ec為0。只有這樣才能訪問套接字以建立連接。要連接的服務(wù)器地址由第二個參數(shù)提供,其類型為boost::asio::ip::tcp::resolver::iterator。該參數(shù)是名稱解析的結(jié)果。

對async_connect()的調(diào)用之后是對處理程序connect_handler()的調(diào)用。再次首先檢查ec以確定是否可以建立連接。如果是這樣,則在套接字上調(diào)用async_read_some()。通過此調(diào)用,開始讀取數(shù)據(jù)。接收到的數(shù)據(jù)存儲在數(shù)組字節(jié)中,作為第一個參數(shù)傳遞給async_read_some()。

當(dāng)接收到一個或多個字節(jié)并將其復(fù)制到字節(jié)時調(diào)用read_handler()。std::size_t類型的參數(shù)bytes_transferred包含已接收的字節(jié)數(shù)。像往常一樣,處理程序應(yīng)該首先檢查異步操作是否成功完成。只有在這種情況下,才會將數(shù)據(jù)寫入標準輸出。

請注意,在將數(shù)據(jù)寫入std::cout后,read_handler()會再次調(diào)用async_read_some()。這是必需的,因為您無法確定整個主頁是否已在單個異步操作中下載并復(fù)制到字節(jié)中。對async_read_some()的重復(fù)調(diào)用和對read_handler()的重復(fù)調(diào)用僅在連接關(guān)閉時結(jié)束,這發(fā)生在網(wǎng)絡(luò)服務(wù)器發(fā)送整個主頁時。然后read_handler()在ec中報告錯誤。此時,不會向std::cout寫入更多數(shù)據(jù),并且不會在套接字上調(diào)用async_read()。因為沒有掛起的異步操作,程序退出。

示例32.6。具有boost::asio::ip::tcp::acceptor的時間服務(wù)器

#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是一個時間服務(wù)器。您可以連接telnet客戶端以獲取當(dāng)前時間。之后時間服務(wù)器關(guān)閉。

時間服務(wù)器使用I/O對象boost::asio::ip::tcp::acceptor來接受來自另一個程序的傳入連接。您必須初始化對象,以便它知道在哪個端口上使用哪個協(xié)議。在示例中,boost::asio::ip::tcp::endpoint類型的變量tcp_endpoint用于告訴tcp_acceptor在端口2014上接受Internet協(xié)議版本4的傳入連接。

接收器初始化后,調(diào)用listen()使接收器開始監(jiān)聽。然后調(diào)用async_accept()以接受第一次連接嘗試。必須將套接字作為第一個參數(shù)傳遞給async_accept(),該參數(shù)將用于在新連接上發(fā)送和接收數(shù)據(jù)。

一旦另一個程序建立連接,就會調(diào)用accept_handler()。如果連接建立成功,當(dāng)前時間會通過boost::asio::async_write()發(fā)送。此函數(shù)將data中的所有數(shù)據(jù)寫入套接字。boost::asio::ip::tcp::socket還提供了成員函數(shù)async_write_some()。此函數(shù)在至少發(fā)送一個字節(jié)時調(diào)用處理程序。然后處理程序必須檢查發(fā)送了多少字節(jié)以及還需要發(fā)送多少字節(jié)。然后,它必須再次調(diào)用async_write_some()。使用boost::asio::async_write()可以避免重復(fù)計算要發(fā)送的字節(jié)數(shù)和調(diào)用async_write_some()。使用此函數(shù)開始的異步操作僅在數(shù)據(jù)中的所有字節(jié)都發(fā)送完畢后才完成。

發(fā)送數(shù)據(jù)后,會調(diào)用write_handler()。該函數(shù)使用參數(shù)boost::asio::ip::tcp::socket::shutdown_send調(diào)用shutdown(),表示程序已完成通過套接字發(fā)送數(shù)據(jù)。由于沒有待處理的異步操作,示例32.6退出。請注意,雖然data僅在accept_handler()中使用,但它不能是局部變量。數(shù)據(jù)通過boost::asio::buffer()引用傳遞到boost::asio::async_write()。當(dāng)boost::asio::async_write()和accept_handler()返回時,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論