一個(gè)同步的
TCP daytime
客戶端
?
?
This tutorial program shows how to use asio to implement a client application with TCP.
We start by including the necessary header files.
?本示例程序顯示如何使用Asio來實(shí)現(xiàn)一個(gè)TCP客戶端程序。
讓我們從添加必需的頭文件開始。
#include?
<
iostream
>
#include?
<
boost
/
array.hpp
>
#include?
<
boost
/
asio.hpp
>
The purpose of this application is to access a daytime service, so we need the user to specify the server.
這個(gè)應(yīng)用程序的目的是訪問一個(gè)daytime服務(wù)器,因此我們需要用戶去指定服務(wù)器。(如time-nw.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
;
????}
All programs that use asio need to have at least one boost::asio::io_service object.
所有使用
asio
的程序都至少需要一個(gè)boost::asio::io_service對(duì)象。
????boost::asio::io_service?io_service;
We need to turn the server name that was specified as a parameter to the application, into a TCP endpoint. To do this we use an boost::asio::ip::tcp::resolver object.
?我們需要把服務(wù)器的名稱轉(zhuǎn)化為TCP的節(jié)點(diǎn),而該名稱是通過應(yīng)用程序的參數(shù)指定的。我們使用boost::asio::ip::tcp::resolver 對(duì)象來完成。
????tcp::resolver?resolver(io_service);
A resolver takes a query object and turns it into a list of endpoints. We construct a query using the name of the server, specified in argv[1]
, and the name of the service, in this case "daytime"
.
一個(gè)
resolver
對(duì)象
獲得一個(gè)
query
對(duì)象
,
并將其轉(zhuǎn)換為節(jié)點(diǎn)列表
.
我們
通過
argv[1]
中的
服務(wù)器名稱
和
服務(wù)名,在這里是
daytime
,構(gòu)造一個(gè)
query
。
??
???tcp::resolver::query?query(argv[
1
],?
"
daytime
"
);
The list of endpoints is returned using an iterator of type boost::asio::ip::tcp::resolver::iterator. A default constructed boost::asio::ip::tcp::resolver::iterator object is used as the end iterator.
節(jié)點(diǎn)列表用 boost::asio::ip::tcp::resolver::iterator
類型的迭代器返回。返回的
iterator
將采用
boos
t::asio::ip::tcp::resolver::iterator
的默認(rèn)構(gòu)造函數(shù)來構(gòu)造。
????tcp::resolver::iterator?endpoint_iterator?
=
?resolver.resolve(query);
????tcp::resolver::iterator?end;
Now we create and connect the socket. The list of endpoints obtained above may contain both IPv4 and IPv6 endpoints, so we need to try each of them until we find one that works. This keeps the client program independent of a specific IP version.
現(xiàn)在我們建立一個(gè)socket并連接之,由于獲得的節(jié)點(diǎn)既有IPv4也有IPv6的。所以,我們需要依次嘗試訪問它們直到找到一個(gè)可以正常工作的。這樣做可使得我們的程序獨(dú)立于特定的IP版本。
????tcp::socket?socket(io_service);
????boost::system::error_code?error?
=
?boost::asio::error::host_not_found;
????
while
?(error?
&&
?endpoint_iterator?
!=
?end)
????{
??????socket.close();
??????socket.connect(
*
endpoint_iterator
++
,?error);
????}
????
if
?(error)
??????
throw
?boost::system::system_error(error);
The connection is open. All we need to do now is read the response from the daytime service.
We use a boost::array
to hold the received data. The boost::asio::buffer() function automatically determines the size of the array to help prevent buffer overruns. Instead of a boost::array
, we could have used a char[]
or std::vector
.
連接打開后,現(xiàn)在我們需要做的就是讀取daytime服務(wù)器的響應(yīng)。
我們使用boost::array 來存放接收到的數(shù)據(jù)。boost::asio::buffer()函數(shù)會(huì)自動(dòng)確定array的長(zhǎng)度來防止緩沖區(qū)溢出。我們也可以使用 char[]
?或 std::vector來代替boost::array。
????
for
?(;;)
????{
??????boost::array
<
char
,?
128
>
?buf;
??????boost::system::error_code?error;
??????size_t?len?
=
?socket.read_some(boost::asio::buffer(buf),?error);
When the server closes the connection, the boost::asio::ip::tcp::socket::read_some() function will exit with the boost::asio::error::eof error, which is how we know to exit the loop.
當(dāng)服務(wù)器關(guān)閉連接時(shí),boost::asio::ip::tcp::socket::read_some()
函數(shù)
會(huì)
以
boost::asio::error::eof
錯(cuò)誤
標(biāo)志
返回
,
通過該錯(cuò)誤標(biāo)志,我們知道應(yīng)該退出循環(huán)了。
??????
if
?(error?
==
?boost::asio::error::eof)
????????
break
;?
//
?Connection?closed?cleanly?by?peer.
??????
else
?
if
?(error)
????????
throw
?boost::system::system_error(error);?
//
?Some?other?error.
??????std::cout.write(buf.data(),?len);
????}
Finally, handle any exceptions that may have been thrown.
最后,處理所有可能拋出的異常 。
??}
??
catch
?(std::exception
&
?e)
??{
????std::cerr?
<<
?e.what()?
<<
?std::endl;
??}
See the
full source listing
完整代碼:
posted on 2008-04-20 01:27
王曉軒 閱讀(1533)
評(píng)論(0) ?
編輯?
收藏引用 所屬分類:
C\C++