-
ACE Tutorial [翻译] 08-page02
2004-11-29
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://jnn.blogbus.com/logs/519776.html
首先,我们看一下server.cpp是如何实现的。 这是一个特别简单的应用,该应用只负责监听指定端口的数据报文,并且将收到的消息转发过去。为了能够真实地展现“服务发现“的机制,服务器需要在确定反馈消息部分做一些特别地工作。这将在我们地下面地教程中详细介绍。
// page02.html,v 1.13 2000/11/27 17:56:43 othman Exp/* Our datagram server will, of course, need to create a datagram.We'll also need an address object so that we know where to listen.我们的数据报文服务器,显而易见,需要创建一个数据报。我们需要一个地址对象来知道我们希望监听的端口*/#include "ace/Log_Msg.h"
#include "ace/SOCK_Dgram.h"
#include "ace/INET_Addr.h"
/* Use the typical TCP/IP port address for receiving datagrams.使用一个典型的TCP/IP端口来接收数据。*/static const u_short PORT = ACE_DEFAULT_SERVER_PORT;intmain (int, char**){/* This is where we'll listen for datagrams coming from the clients.
We'll give this address to the open() method below to enable thelistener.这里我是我们接收客户端所发送过来的数据报。我们使用这个地址来打开我们所希望的监听。*/ACE_INET_Addr local (PORT);/* A simply constructed datagram that we'll listen with.
简单构造函数来创建我们所希望监听的数据报*/ACE_SOCK_Dgram dgram;/* Like most ACE objects, the datagram has to be opened before it
can be uses. Of course, -1 on failure.和其他的ACE对象一样,数据报在使用的之前需要调用open方法。当然,如果调用失败返回值为-1。A datagram will fail to open if there is already a datagramlistening at the port we've chosen. It *is* OK to open a datagramat a port where there is an ACE_SOCK_Stream though. This isbecause datagrams are UDP and SOCK_Stream is TCP and the two don'tcross paths.如果在我们所选定的端口已经在监听数据报了,那么数据报接收器在创建的时候会出现错误。但是它在打开一个ACE_SOCK_Stream所占用的端口是没有问题的。这是由于UDP的数据报文和TCP SOCK_Stream的端口是不相关的。*/if (dgram.open (local) == -1)ACE_ERROR_RETURN ((LM_ERROR,"%p\n",
"open"),
-1);/* Create a simple buffer to receive the data. You generally need
to provide a buffer big enough for the largest datagram you expectto receive. Some platforms will let you read a little and thensome more later but other platforms will throw out whatever partof the datagram you don't get with the first read. (This is on aper-datagram basis BTW.) The theoretical limit on a datagram isabout 64k. The realistic limit (because of routers & such) ismuch smaller. Choose your buffer size based on your application'sneeds.为接收到的数据创建一个缓冲区。你需要设置一个比你所期望接收的数据报更大一些的缓冲区。一些系统平台运行你读取一小部分数据,过一段时间之后在继续读剩余的内容,但是另一下系统平台在你第一次读取部分数据之后,就将数据报的剩余内容丢弃。(这是一个面向单数据报的模式。)一个数据报的理论最大值是64K。在现实中的最大值(由于路由或者其他)比这个值要小很多。你需要根据应用需要选择你的缓冲大小。*/char buf[BUFSIZ];/* Unlike ACE_SOCK_Stream, datagrams are unconnected. That is,
there is no "virtual circuit" between server and client. Because
of this, the server has to provide a placeholder for the OS tofill in the source (client) address information on the recv. Youcan initialize this INET_Addr to anything, it will be overwrittenwhen the data arrives.与ACE_SOCK_Stream不同,数据报是非面向连接的。这就是说,在服务器和客户端之间是没有”虚拟链路”的。正是因为这样,服务器需要提供存储空间来为存放操作
系统接收到的(客户端)的地址信息。你可以给INET_Addr初始化任何一个值,当接收到数据报时,这个值将会被覆盖。*/ACE_INET_Addr remote;ACE_DEBUG ((LM_DEBUG,"(%P|%t) starting up server daemon\n"));
/* Receive datagrams as long as we're able.
一直接收我们所能接收到的数据报*/while (dgram.recv (buf,sizeof (buf),remote) != -1){/* Display a brief message about our progress. Notice how we
use the 'remote' object to display the address of the client.With an ACE_SOCK_Stream we used get_remote_addr() to get theaddress the socket is connected to. Because datagrams areunconnected, we use the addr object provided to recv().显示现在进展情况的简要信息。注意我们怎样使用‘remot’对象来显示客户端的地址。在ACE_SOCK_Stream中,我们使用get_remote_addr()来获取连接到我们的socket地址。由于数据报时非面向连接的,我们使用recv()方法所提供的地址对象来获取。*/ACE_DEBUG ((LM_DEBUG,"(%P|%t) Data (%s) from client (%s)\n",
buf,remote.get_host_name ()));/* To respond to the client's query, we have to become a client
ourselves. To do so, we need an anonymous local address fromwhich we'll send the response and a datagram in which to sendit. (An anonymous address is simply one where we let the OSchoose a port for us. We really don't care what it is.为了响应客户端的请求。我们需要创建一个客户端对象。为了这样做,我们需要一个匿名的本地地址,这样我们可以通过这个地址向发送响应的数据报。(一个匿名地址包含操作系统提供为我们选定的一个端口号,在这里,我们并不关心其详细内容)*/ACE_INET_Addr local ((u_short) 0);ACE_SOCK_Dgram client;/* Open up our response datagram as always.初始化我们的响应报文*/if (client.open (local) == -1){ACE_ERROR_RETURN ((LM_ERROR,"%p\n",
"client open"),
-1);return 0;}/* Build a witty response...创建一个诙谐的响应*/sprintf (buf,"I am here");
/* and send it to the client. Notice the symmetry with the
recv() method. Again, the unconnected nature of datagramsforces us to specify an address object with each read/writeoperation. In the case of read (recv()) that's where the OSstuffs the address of the datagram sender. In the case ofwrite (send()) that we're doing here, the address is where wewant the network to deliver the data.将信息回传到客户端。注意这是一个和recv()方法对应的函数。由于数据报时非面向连接的,这就要求我们在进行读写操作时,需要指明地址对象。在读取(recv())情况下,我们从操作系统获得的地址,就是发送数据的源地址在写数据(send())时,这个地址就是我们希望发送的目的地址。Of course, we're assuming that the client will be listeningfor our reply...当然,我们需要假设客户端已经在监听我们的回应了…
*/if (client.send (buf,ACE_OS::strlen (buf) + 1,
remote) == -1)ACE_ERROR_RETURN ((LM_ERROR,"%p\n",
"send"),
-1);}return 0;}
这就是我们涉及到的内容。显然这里还有很多可以扩展的空间。这里最值得争议的是在接收报文时设置小一点的缓冲区。现在我还不能给一个明确的设置数据报大小的回答。理论上来说,缓冲区有一个64K大小的限制,所以你需要自己进行关分包的操作。一些文章指出8K是一般比较合适的大小,其他这说更小一点的数据包比较合适。我认为最好的保证数据尽可能小(例如――小于8K)并且进行大量测试。如果你发现你的路由器已经对你的大数据报进行了分包的操作,你需要减小你的数据包的大小。当然,如果你需要发送100K并且一次只能发送1K,你需要考虑有关重传或者从组的问题。从这一点来说,你也许会考虑采用TCP。
注意:数据包是不可靠的。
历史上的今天:
ACE Tutorial [翻译] 08-page04 2004-11-29ACE Tutorial [翻译] 08-page03 2004-11-29ACE Tutorial [翻译] 08-page01 2004-11-29随机文章:
ACE Tutorial [翻译] 08-page04 2004-11-29ACE Tutorial [翻译] 08-page03 2004-11-29ACE Tutorial [翻译] 08-page01 2004-11-29ACE Tutorial [翻译] 06 -page05 2004-11-21ACE Tutorial [翻译] 06 -page04 2004-11-21
收藏到:Del.icio.us







