boost::asio编程-同步TCP
boost.asio库是一个跨平台的网络及底层IO的C++编程库,它使用现代C++手法实现了统一的异步调用模型。
boost.asio库支持TCP、UDP、ICMP通信协议。
下面介绍同步TCP模式:
大家好!我是同步方式!
我的主要特点就是执着!所有的操作都要完成或出错才会返回,不过偶的执着被大家称之为阻塞,实在是郁闷~~(场下一片嘘声),其实这样 也是有好处的,比如逻辑清晰,编程比较容易。
在服务器端,我会做个socket交给acceptor对象,让它一直等客户端连进来,连上以后再通过这个socket与客户端通信, 而所有的通信都是以阻塞方式进行的,读完或写完才会返回。
在客户端也一样,这时我会拿着socket去连接服务器,当然也是连上或出错了才返回,最后也是以阻塞的方式和服务器通信。
有人认为同步方式没有异步方式高效,其实这是片面的理解。在单线程的情况下可能确实如此,我不能利用耗时的网络操作这段时间做别的事 情,不是好的统筹方法。不过这个问题可以通过多线程来避免,比如在服务器端让其中一个线程负责等待客户端连接,连接进来后把socket交给另外的线程去 和客户端通信,这样与一个客户端通信的同时也能接受其它客户端的连接,主线程也完全被解放了出来。
我的介绍就有这里,谢谢大家!
同步方式示例代码:
服务器端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
// BoostTcpServer.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "boost/asio.hpp"
#include "boost/thread.hpp"
using namespace std;
using namespace boost::asio;
#ifdef _MSC_VER
#define _WIN32_WINNT 0X0501 //避免VC下编译警告
#endif
#define PORT 1000
#define IPV6
//#define IPV4
int _tmain( int argc, _TCHAR* argv[])
{
// 所有asio类都需要io_service对象
io_service iosev;
//创建用于接收客户端连接的acceptor对象
#ifdef IPV4
ip::tcp::acceptor acceptor(iosev,ip::tcp::endpoint(ip::tcp::v4(), PORT));
#endif
#ifdef IPV6
ip::tcp::acceptor acceptor(iosev,ip::tcp::endpoint(ip::tcp::v6(), PORT));
#endif
while ( true )
{
// socket对象
ip::tcp::socket socket(iosev);
// 等待直到客户端连接进来
acceptor.accept(socket);
// 显示连接进来的客户端
std::cout << "remote ip:" <<socket.remote_endpoint().address()<<endl;
std::cout << "remote port:" <<socket.remote_endpoint().port() << std::endl;
char buf[2048];
boost:: system ::error_code ec;
while (1)
{
socket.read_some(buffer(buf),ec);
if (ec)
{
std::cout <<boost:: system ::system_error(ec).what() << std::endl;
break ;
}
std::cout<< "recv msg:" <<buf<<endl;
if ( strcmp (buf, "bye" )==0) //收到结束消息结束客户端连接
{
break ;
}
socket.write_some(buffer( "I heared you!\n" ),ec);
if (ec)
{
std::cout <<boost:: system ::system_error(ec).what() << std::endl;
break ;
}
}
socket.close();
// 与当前客户交互完成后循环继续等待下一客户连接
}
return 0;
}
|
客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
// BoostTcpClient.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "boost/asio.hpp"
using namespace boost::asio;
#ifdef _MSC_VER
#define _WIN32_WINNT 0X0501 //避免VC下编译警告
#endif
#define PORT 1000
#define IPV6
//#define IPV4
int _tmain( int argc, _TCHAR* argv[])
{
// 所有asio类都需要io_service对象
io_service iosev;
// socket对象
ip::tcp::socket socket(iosev);
// 连接端点,这里使用了本机连接,可以修改IP地址测试远程连接
#ifdef IPV4
ip::address_v4 address=ip::address_v4::from_string( "127.0.0.1" );
#endif
#ifdef IPV6
//"0:0:0:0:0:0:0:1"为IPV6的本机回环地址,类似于"127.0.0.1"
ip::address_v6 address=ip::address_v6::from_string( "0:0:0:0:0:0:0:1" );
#endif
ip::tcp::endpoint ep(address, PORT);
// 连接服务器
boost:: system ::error_code ec;
socket.connect(ep,ec);
// 如果出错,打印出错信息
if (ec)
{
std::cout << boost:: system ::system_error(ec).what() << std::endl;
return -1;
}
//循环发送和接收数据
for ( int i=0;i<5;++i)
{
//发送数据
socket.write_some(buffer( "hello" ), ec);
// 接收数据
char buf[100];
size_t len=socket.read_some(buffer(buf), ec);
std::cout.write(buf, len);
Sleep(500);
}
//发送与服务端约定好的结束语,由服务端断链
socket.write_some(buffer( "bye" ), ec);
getchar ();
return 0;
}
|
代码中兼容了IPV4和IPV6两种IP协议,使用宏定义选择使用哪种IP协议,当然客户端和服务端的协议必须一致才能正常通信。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!