ACE网络库的UDP通信(数据报)的使用

使用ACE的数据报

        ACE_SOCK_Dgram和ACE_LSOCK_Dgram是ACE中的数据报包装类。这些包装包含了发送和接收数据报的方法,并包装了非面向连接的UDP协议和UNIX域socket协议。与流包装不同,这些包装封装的是非面向连接的协议。这也就意味着不存在用于“设置”连接的接受器和连接器。相反,在这种情况下,通信通过一系列的发送和接收来完成。每个send()都要指定目的远地地址作为参数。下面的例子演示怎样通过ACE使用数据报。这个例子使用了ACE_SOCK_Dgram包装(也就是UDP包装)。还可以使用包装UNIX域数据报的ACE_LSOCK_Dgram。两种包装的用法非常类似,唯一的不同是ACE_LSOCK_Dgram要用ACE_UNIX_Addr类作为地址,而不是ACE_INET_Addr。


#pragma once
//例2 - 3
//Server
#include "stdafx.h"
#include "ace/Log_Msg.h"
#include "ace/OS.h"
#include "ace/SOCK_Dgram.h"
#include "ace/INET_Addr.h"

#define DATA_BUFFER_SIZE 1024
#define SIZE_DATA 19

class Server
{
public:
	Server(int local_port)
		:local_addr_(local_port), local_(local_addr_)
	{
		data_buf = new char[DATA_BUFFER_SIZE];
	}
	//Expect data to arrive from the remote machine. Accept it and display
	//it. After receiving data, immediately send some data back to the
	//remote.
	int accept_data()
	{
		int byte_count = 0;
		while ((byte_count = local_.recv(data_buf, SIZE_DATA, remote_addr_)) != -1)
		{
			data_buf[byte_count] = 0;
			ACE_DEBUG((LM_DEBUG, "Data received from remote %s was %s /n"
				, remote_addr_.get_host_name(), data_buf));
			ACE_OS::sleep(1);
			if (send_data() == -1) break;
		}
		return -1;
	}
	//Method used to send data to the remote using the datagram component
	//local_
	int send_data()
	{
		ACE_DEBUG((LM_DEBUG, "Preparing to send reply to client %s:%d/n",
			remote_addr_.get_host_name(), remote_addr_.get_port_number()));
		ACE_OS::sprintf(data_buf, "Server says hello to you too");
		if (local_.send(data_buf, ACE_OS::strlen(data_buf) + 1, remote_addr_) == -1)
			return -1;
		else
			return 0;
	}
private:
	char *data_buf;
	ACE_INET_Addr remote_addr_;
	ACE_INET_Addr local_addr_;
	ACE_SOCK_Dgram local_;
};


int main(int argc, char *argv[])
{
	if (argc < 2)
	{
		ACE_DEBUG((LM_DEBUG, "Usage %s <Port Number>", argv[0]));
		ACE_OS::exit(1);
	}
	Server server(ACE_OS::atoi(argv[1]));
	server.accept_data();
	return 0;
}


        上面的代码是一个简单的服务器,它等待客户应用通过已知端口给它发送一个数据报。在该数据报中含有定长的和预定数量的数据。服务器在收到这些数据时,就发送回复给原先发送数据的客户。
Server类拥有名为local_的ACE_SOCK_Dgram私有成员,它被同时用于接收和发送数据。Server在它的构造器中通过已知的ACE_INET_Addr(本地主机以及已知端口)实例化local_,这样客户就可以对它进行定位、并发送消息给它了。

        Server主函数实例化相应的客户代码与前面的服务器例子非常类似:
类包含两个方法:accept_data(),用于从客户接收数据(使用recv()调用包装);以及send_data(),用于发送数据给远地客户(使用send()调用包装)。注意local_包装类的send()和receive()的底层调用都包装了BSD sendto()和recvfrom()调用,并具有相类似的特征。Server类型的对象、并调用它的accept_data()方法,等待来自客户的数据。当它得到所需的数据后,它调用send_data()发送回复消息给客户。如此循环往复,直到客户被关闭为止。


相应的客户端代码与前面的服务端代码非常相似:

//例2 - 4
//Client
// ACE_Dgram_Client.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "ace/Log_Msg.h"
#include "ace/OS.h"
#include "ace/SOCK_Dgram.h"
#include "ace/INET_Addr.h"

#define DATA_BUFFER_SIZE 1024
#define SIZE_DATA 28

class Client
{
public:
	Client(char * remote_host, int port)
		:remote_addr_(remote_host),
		local_addr_((u_short)0), local_(local_addr_)
	{
		data_buf = new char[DATA_BUFFER_SIZE];
		remote_addr_.set_port_number(port);
	}
	//Receive data from the remote host using the datgram wrapper `local_’.
	//The address of the remote machine is received in `remote_addr_’
	//which is of type ACE_INET_Addr. Remember that there is no established
	//connection.
	int accept_data()
	{
		if (local_.recv(data_buf, SIZE_DATA, remote_addr_) != -1)
		{
			ACE_DEBUG((LM_DEBUG, "Data received from remote server %s was: %s /n",
				remote_addr_.get_host_name(), data_buf));
			return 0;
		}
		else
			return -1;
	}
	//Send data to the remote. Once data has been sent wait for a reply
	//from the server.
	int send_data()
	{
		ACE_DEBUG((LM_DEBUG, "Preparing to send data to server %s:%d/n",
			remote_addr_.get_host_name(), remote_addr_.get_port_number()));
		ACE_OS::sprintf(data_buf, "Client says hello");
		while (local_.send(data_buf, ACE_OS::strlen(data_buf), remote_addr_) != -1)
		{
			ACE_OS::sleep(1);
			if (accept_data() == -1)
				break;
		}
		return -1;
	}
private:
	char *data_buf;
	ACE_INET_Addr remote_addr_;
	ACE_INET_Addr local_addr_;
	ACE_SOCK_Dgram local_;
};


int main(int argc, char *argv[])
{
	if (argc < 3)
	{
		ACE_OS::printf("Usage: %s <hostname> <port_number> /n", argv[0]);
		ACE_OS::exit(1);
	}
	Client client(argv[1], ACE_OS::atoi(argv[2]));
	client.send_data();
	return 0;
}


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qing666888/article/details/51501777
个人分类: C/C++ 网络编程
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭