#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<char, 128> 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;
}
}
#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<char, 128> 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;
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;
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,0, sizeof(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;
}
#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,0, sizeof(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;
}