2 C++ ACE  基本IO对象 TCP/UDP/HTTP的Server/Client 组播广播



ACE I/O相关对象



阻塞式 TCP连接Linux Kernel网站服务器的443端口

非阻塞模式 TCP连接百度服务器

设置 TCP连接超时:

ACE 客户端 TCP模式.请求HTTP


一个简单的 TCP HTTP server
	HTTP server 代码
	创建网页文件
	浏览器测试访问结果

ACE UDP通信单播测试:
	UDP 单播 服务器端:
	UDP 单播 客户端:

ACE UDP 多播实验:	
	UDP 多播 发送端程序:
	UDP 多播 接收端程序:


UDP 广播实验
	UDP 广播发送端
	UDP 广播接收端 	
	
	



阻塞式 TCP连接Linux Kernel网站服务器的443端口

chunli@linux:~$ cat main.cpp 
#include <iostream>
#include <ace/INET_Addr.h>
#include <ace/SOCK_Connector.h>
#include <ace/SOCK_Stream.h>
int main(void)
{
	ACE_SOCK_Connector connector;
	ACE_SOCK_Stream peer;
	ACE_INET_Addr peerAddr;
	
	if(peerAddr.set(443,"www.kernel.org") == -1)
	{
		std::cerr << "peerAddr.set set error\n";
		return -1;
	}
	else if(connector.connect(peer,peerAddr) == -1)
	{
		std::cerr << "connector.connect error\n";
		return -1;
	}
	std::cout << "Hello ACE\n";
	return 0;
}
chunli@linux:~$ g++ -Wall main.cpp -l ACE && ./a.out 
Hello ACE
chunli@linux:~$


非阻塞模式 TCP连接百度服务器

chunli@linux:~$ cat main.cpp 
#include <iostream>
#include <ace/INET_Addr.h>
#include <ace/SOCK_Connector.h>
#include <ace/SOCK_Stream.h>
int main(void)
{
	ACE_SOCK_Connector connector;
	ACE_SOCK_Stream peer;
	ACE_INET_Addr peerAddr;
	
	if(peerAddr.set(443,"www.baidu.com") == -1)
	{
		std::cerr << "peerAddr.set set error\n";
		return -1;
	}
	if(connector.connect(peer,peerAddr,&ACE_Time_Value::zero) == -1)//传一个时间指针,时间是0,不需要等
	{
		if(errno == EWOULDBLOCK)//如果不能设置为非阻塞
		{
			std::cerr << "不能设置为非阻塞\n";
		}
		if(connector.connect(peer,0,&ACE_Time_Value::zero) == -1)
		{
			std::cerr << "connector.connect error\n";
		}
		else
		{
			std::cout << "Hello ACE\n";
		}	
	}
	else
	{
		std::cout << "Hello ACE\n";
	}

	return 0;
}
chunli@linux:~$ g++ -Wall main.cpp -l ACE && ./a.out 
不能设置为非阻塞
connector.connect error
chunli@linux:~$


设置 TCP连接超时:

chunli@linux:~$ cat main.cpp 
#include <iostream>
#include <ace/INET_Addr.h>
#include <ace/SOCK_Connector.h>
#include <ace/SOCK_Stream.h>
int main(void)
{
	ACE_SOCK_Connector connector;
	ACE_SOCK_Stream peer;
	ACE_INET_Addr peerAddr;
	ACE_Time_Value timeout(1);	//超时设置
	
	if(peerAddr.set(443,"www.baidu.com") == -1)
	{
		std::cerr << "peerAddr.set set error\n";
		return -1;
	}
	if(connector.connect(peer,peerAddr,&timeout) == -1)//传一个时间指针,时间是0,不需要等
	{
		if(errno == ETIME)
		{
			std::cerr << " 连接超时\n";
		}
	}
	else
	{
		std::cout << "Hello ACE\n";
	}
	return 0;
}
chunli@linux:~$ g++ -Wall main.cpp -l ACE && ./a.out 
Hello ACE
chunli@linux:~$


ACE 客户端 TCP模式.请求HTTP

chunli@linux:~/ACE$ cat main.cpp 
#include <iostream>
#include <ace/INET_Addr.h>
#include <ace/SOCK_Connector.h>
#include <ace/SOCK_Stream.h>
#include <ace/Log_Msg.h>
int main(void)
{
	ACE_SOCK_Connector connector;
	ACE_SOCK_Stream peer;
	ACE_INET_Addr peerAddr;
	
	if(peerAddr.set(443,"www.baidu.com") == -1)
	{
		ACE_ERROR_RETURN((LM_ERROR,"%p\n","set()"),1);
	}
	else if(connector.connect(peer,peerAddr) == -1)
	{
		ACE_ERROR_RETURN((LM_ERROR,"%p\n","connect()"),1);
	}
	char buf[BUFSIZ];	//BUFSIZ 8192
	iovec iov[3];
	iov[0].iov_base = (char*) "GET";
	iov[0].iov_len = 4;
	iov[1].iov_base = (char*) "/index.php";
	iov[1].iov_len = 10;
	//iov[2].iov_base = (char*) "HTTP/1.0\r\n\r\n";
	iov[2].iov_base = (char*) "HTTP/1.0";
	iov[2].iov_len = 13;
	if(peer.sendv_n(iov,3) == -1)
	{
		ACE_ERROR_RETURN((LM_ERROR,"%p\n","sendv_n()"),1);
	}
	ssize_t n;
	while((n = peer.recv(buf,sizeof(buf))) > 0 )
	{
		ACE::write_n(ACE_STDOUT,buf,n);
	}
	return peer.close();
}
chunli@linux:~/ACE$ 

编译运行:
chunli@linux:~/ACE$ 
chunli@linux:~/ACE$ g++ main.cpp -l ACE -Wall && ./a.out  
HTTP/1.1 302 Moved Temporarily
Server: bfe/1.0.8.18
Date: Fri, 28 Oct 2016 12:55:54 GMT
Content-Type: text/html
Content-Length: 17931
Connection: close
ETag: "54d9748e-460b"

<html>
<head>
<div id="content_left">
<div class="nors">
<div class="norsSuggest">
	<h3 class="norsTitle">很抱歉,您要访问的页面不存在!</h3>
	<p class="norsTitle2">温馨提示:</p>
	<ol>
		<li>请检查您访问的网址是否正确</li> 
		<li>如果您不能确认访问的网址,请浏览<a href="http://www.baidu.com/more/index.html">百度更多</a>页面查看更多网址。</li>
		<li>回到顶部重新发起搜索</li>
		<li>如有任何意见或建议,请及时<a href="http://qingting.baidu.com/index">反馈给我们</a>。</li>
		

	</ol>
</div>
</div>
</div>


一个简单的 TCP HTTP server

chunli@linux:~/ACE$ cat main.cpp 
#include <string.h>

#include <ace/INET_Addr.h>
#include <ace/SOCK_Acceptor.h>
#include <ace/SOCK_Stream.h>
#include <ace/Mem_Map.h>
#include <ace/Log_Msg.h>

extern char *get_url_pathname(ACE_SOCK_Stream *);

int main(void)
{
	ACE_INET_Addr 		server_addr;
	ACE_SOCK_Acceptor 	acceptor;
	ACE_SOCK_Stream 	peer;
	if(server_addr.set(11223) == -1)//监听端口随意选,有些端口需要root权限才可以
	{
		ACE_ERROR_RETURN((LM_ERROR,"%p\n","set()"),1);
	}
	if(acceptor.open(server_addr) == -1)
	{
		ACE_ERROR_RETURN((LM_ERROR,"%p\n","open()"),1);
	}
	while(1)
	{
		if(acceptor.accept(peer) == -1)
		{
			ACE_ERROR_RETURN((LM_ERROR,"%p\n","accept()"),1);
		}
		peer.disable(ACE_NONBLOCK);
		char * pathname = get_url_pathname(&peer);
		if(pathname == NULL)
		{
			ACE_ERROR_RETURN((LM_ERROR,"%p\n","get_url_pathname()"),1);
		}
		ACE_Mem_Map mapped_file(pathname);
		delete [] pathname;
		if(peer.send_n(mapped_file.addr(),mapped_file.size()) == -1)
		{
			ACE_ERROR_RETURN((LM_ERROR,"%p\n","send_n()"),1);
		}
		peer.close();
	}
	return acceptor.close() == -1?1:0;
}

char* get_url_pathname(ACE_SOCK_Stream* peer)
{
	static const char * docBase = "./pages";
	char buf[512];
	if(peer->recv(buf,sizeof(buf)) != -1)
	{
		// request example:
		// GET /index.html HTTP/1.0\r\n
		const char *pos1 = strchr(buf,' ');
		const char *pos2 = strchr(++pos1,' ');
		const size_t len = pos2 - pos1;
		const size_t docLen = strlen(docBase);
		char* path = new char [len + docLen +1];
		memcpy(path,docBase,docLen);
		memcpy(path+docLen,pos1,len);
		return path;
	}
	return NULL;
}

既然是一个HTTP服务器,那么我得准备网页文件:
创建网页文件:
chunli@linux:~/ACE$ cat pages/hello.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>标题文字</title>
</head> 
<body >
	<h1> 测试啊.....................</h1>
</body>
</html>
chunli@linux:~/ACE$ 

编译运行:
chunli@linux:~/ACE$ g++ main.cpp -l ACE -Wall && ./a.out

另开窗口查看监听:
chunli@linux:/tmp$ netstat -tnlpa  | grep 11223
tcp        0      0 0.0.0.0:11223           0.0.0.0:*               LISTEN      2060/a.out      

浏览器测试访问结果:
chunli@linux:/tmp$ curl  localhost:11223/hello.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>标题文字</title>
</head> 
<body >
	<h1> 测试啊.....................</h1>
</body>
</html>
chunli@linux:/tmp$ 
实验完毕!



ACE UDP通信单播测试


UDP 单播 服务器端:

chunli@linux:~/ACE$ cat udp_server.cpp 
/*****************************************************************
  功能:ACE UDP server
  描述:使用ACE网络库,实现简单的UDP服务器程序,监听在本机的8080端口
  作者:魂斗罗
  日期:2016.10.29
  邮箱:li_chunli@mail.com
  版本:1.0
 ******************************************************************/
#include <string.h>
#include <ace/INET_Addr.h>
#include <ace/SOCK_Dgram.h>
#include <ace/Time_Value.h>
#include <ace/Log_Msg.h>

int main(int agrc,char** argv)
{
	ACE_INET_Addr 		serverAddr(8080);
	ACE_SOCK_Dgram		peer(serverAddr);
	char buf[BUFSIZ];
	while(1)
	{
		memset(buf,0,BUFSIZ);
		ACE_INET_Addr	remoteAddr;
		size_t	len = peer.recv(buf,BUFSIZ,remoteAddr);
		if(len > 0)
		{
			peer.send(buf,BUFSIZ,remoteAddr);
			ACE_DEBUG((LM_DEBUG,"%s %s \n","recv",buf));
		}
	}
}
chunli@linux:~/ACE$ 

服务器编译运行:
chunli@linux:~/ACE$ g++ udp_server.cpp -l ACE -Wall && ./a.out 
recv hello ACE 
recv 中文测试 
^C
chunli@linux:~/ACE$


UDP 单播 客户端:

UDP 单播 客户端:

chunli@linux:~/ACE$ cat udp_client.cpp 
/*****************************************************************
  功能:ACE UDP client
  描述:使用ACE网络库,实现简单的UDP客户端程序,向远程主机的8080端口发数据
  作者:魂斗罗
  日期:2016.10.29
  邮箱:li_chunli@mail.com
  版本:1.0
 ******************************************************************/
#include <string.h>
#include <iostream>
#include <ace/INET_Addr.h>
#include <ace/SOCK_Dgram.h>
#include <ace/Time_Value.h>
#include <ace/Log_Msg.h>

int main(int agrc,char** argv)
{
	ACE_INET_Addr           remoteAddr(8080,"11.11.11.6");
	ACE_INET_Addr           localAddr;
        ACE_SOCK_Dgram          peer(localAddr);
        char buf[BUFSIZ];
        while(1)
        {
                memset(buf,0,BUFSIZ);
		std::cin.getline(buf,BUFSIZ);
		if(0 == strcmp("quit",buf))
		{
			break;
		}
		ssize_t len = peer.send(buf,strlen(buf),remoteAddr);
		if(len > 0)
		{
			ACE_DEBUG((LM_DEBUG,"%s \n",buf));
		}
        }
	return 0;
}
chunli@linux:~/ACE$ 

客户端编译运行:
chunli@linux:~/ACE$ g++ udp_client.cpp -l ACE -Wall  -o client && ./client 
hello ACE      
hello ACE 
中文测试
中文测试 
^C
chunli@linux:~/ACE$


ACE UDP 多播实验:

UDP 多播 发送端程序:

chunli@linux:~/ACE$ cat udp_mulitcast_send.cpp 
/*****************************************************************
  功能:ACE UDP 多播 发送端
  描述:使用ACE网络库,实现简单的UDP ,读取键盘,多播发送
  作者:魂斗罗
  日期:2016.10.29
  邮箱:li_chunli@mail.com
  版本:1.0
 ******************************************************************/
#include <iostream>
#include <ace/SOCK_Dgram_Mcast.h>
#include <ace/Log_Msg.h>
int main(int argc,char ** argv)
{
	ACE_INET_Addr		mcastAddr(9988,"224.0.0.16");
	ACE_INET_Addr		localAddr;
	ACE_SOCK_Dgram		scok(localAddr);
	char buf[128];
	while(1)
	{
		memset(buf,0,sizeof(buf));
		std::cin.getline(buf,sizeof(buf));
		if(0 == strcmp("quit",buf))
		{
			break;
		}
		if(scok.send(buf,sizeof(buf),mcastAddr) == -1)
		{
			ACE_ERROR_RETURN((LM_ERROR,"%p \n","send"),1);
		}
	}
	return 0;
}

chunli@linux:~/ACE$ g++ udp_mulitcast_send.cpp -l ACE -Wall -o send && ./send
Hello ACE
中文测试
quit
chunli@linux:~/ACE$


UDP 多播 接收端程序:

chunli@linux:~/ACE$ cat udp_mulitcast_recv.cpp 
/*****************************************************************
  功能:ACE UDP 多播 接收端
  描述:使用ACE网络库,实现简单的UDP 多播功能
  作者:魂斗罗
  日期:2016.10.29
  邮箱:li_chunli@mail.com
  版本:1.0
 ******************************************************************/
#include <iostream>
#include <ace/SOCK_Dgram_Mcast.h>
#include <ace/Log_Msg.h>
int main(int argc,char ** argv)
{
	ACE_INET_Addr           mcastAddr(9988,"224.0.0.16");
	ACE_INET_Addr           remoteAddr;
	ACE_SOCK_Dgram_Mcast    sock;
	if(sock.join(mcastAddr) == -1)
	{
		ACE_ERROR_RETURN((LM_ERROR,"%p \n","join"),1);
	}
	char buf[BUFSIZ];
	while(1)
	{
		memset(buf,0,sizeof(buf));
		if(sock.recv(buf,sizeof(buf),remoteAddr) != -1)
		{
			ACE_DEBUG((LM_DEBUG,"recv msg from %s: %d: %s\n",remoteAddr.get_host_addr(),remoteAddr.get_port_number(),buf));
		}
		//if(sock.leave(mcastAddr) == -1)
		{
		//	ACE_ERROR_RETURN((LM_ERROR,"%p \n","leave"),1);
		}
	}
	return 0;
}
chunli@linux:~/ACE$ 

多开几个接收端:
窗口1
chunli@linux:~/ACE$ g++ udp_mulitcast_recv.cpp -l ACE -Wall  -o recv && ./recv
recv msg from 11.11.11.6: 45245: Hello ACE
recv msg from 11.11.11.6: 45245: 中文测试
窗口2
chunli@linux:~/ACE$ g++ udp_mulitcast_recv.cpp -l ACE -Wall  -o recv && ./recv
recv msg from 11.11.11.6: 45245: Hello ACE
recv msg from 11.11.11.6: 45245: 中文测试
窗口3
chunli@linux:~/ACE$ g++ udp_mulitcast_recv.cpp -l ACE -Wall  -o recv && ./recv
recv msg from 11.11.11.6: 45245: Hello ACE
recv msg from 11.11.11.6: 45245: 中文测试


UDP 广播测试 

UDP 广播发送端 ip:11.11.11.6

chunli@linux:~/ACE$ cat broadcast_send.cpp 
#include <iostream>
#include <ace/SOCK_Dgram_Bcast.h>
#include <ace/Log_Msg.h>
int main(void)
{
	ACE_SOCK_Dgram_Bcast		sock(ACE_Addr::sap_any);
	u_short				port = 8080;
	char buf[BUFSIZ];
	while(1)
	{
		memset(buf,0,sizeof(buf));
		std::cin.getline(buf,sizeof(buf));
		if(0 == strcmp("quit",buf))
			break;
		if(sock.send(buf,strlen(buf),port) == -1)
		{
			ACE_ERROR_RETURN((LM_ERROR,"%p \n","send"),1);
		}
	}
	return 0;
}
chunli@linux:~/ACE$ g++ broadcast_send.cpp -l ACE -Wall -o send && ./send
Hello ACE
测试啊测试..........
quit
chunli@linux:~/ACE$



UDP 广播接收端 ip:11.11.11.17

chunli@ubuntu14:~$ cat broadcast_recv.cpp 
#include <ace/SOCK_Dgram_Bcast.h>
#include <ace/Log_Msg.h>
int main(void)
{
	ACE_INET_Addr		localAddr(8080);
	ACE_INET_Addr		remoteAddr;
	ACE_SOCK_Dgram_Bcast	sock(localAddr);
	char buf[512];
	while(1)
	{
		memset(buf,0,sizeof(buf));
		if(sock.recv(buf,sizeof(buf),remoteAddr) != -1)
		{
			ACE_DEBUG((LM_DEBUG,"recv msg from %s:%d %s\n",remoteAddr.get_host_addr(),remoteAddr.get_port_number(),buf));
		}
	}
	return 0;
}

chunli@ubuntu14:~$ g++ broadcast_recv.cpp  -l ACE -Wall -o bcast_recv && ./bcast_recv
recv msg from 11.11.11.6:50904 Hello ACE
recv msg from 11.11.11.6:50904 测试啊测试..........
^C
chunli@ubuntu14:~$