• ACE Tutorial [翻译] 08-page03

    2004-11-29

    Tag:ACE_TAO

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://jnn.blogbus.com/logs/520210.html

    directed_client.cpp我们创建一个客户端来向指定的服务器发送数据报。如果你知道服务器在什么地方,这是一个比较好的建立连接的方法。例如在Unix中的talk服务,就是采用这样的方式来实现的。


    // page03.html,v 1.13 2000/11/27 17:56:43 othman Exp
     
    #include "ace/Log_Msg.h"
    #include "ace/SOCK_Dgram.h"
    #include "ace/INET_Addr.h"
     
    /* Once again, we use the default server port.  In a "real" system,
       the server's port (or ports) would be published in some way so that
       clients would know where to "look".  We could even add entries to
       the operating system's services file and use a service name instead
       of a number.  We'll come back to that in some other tutorial
       though.  For now, let's stay simple. 
       这里,我们还是选定缺省的服务器端口好。在实际系统中,服务器的端口号
    (端口号组)可以通过某种方式来发布,这样客户端就知道如何来查找服务器。
     我们也可以通过向操作系统的服务文件添加项目,通过项目来取代相应的数字。
     如果感兴趣的化,可以通过其他的教程来学习相关的内容。
     */
    static const u_short PORT = ACE_DEFAULT_SERVER_PORT;
     
    /* Our goal here is to develop a client that can send a datagram to a
       server running on a known host.  We'll use a command-line argument
       to specify the hostname instead of hard-coding it. 
       我们目前要实现的功能就是要开发一个客户端,能够向指定的服务器发送数据报。
       我们使用命令行参数来指定相关的主机,而不是写进我们到我们的代码里。 
    */
    int
    main (int argc,char *argv[])
    {
      /* All datagrams must have a point of origin.  Since we intend to
        transmit instead of receive, we initialize an address with zero
        and let the OS choose a port for us.  We could have chosen our own
        value between 1025 and 65535 as long as it isn't already in use.
    所有的数据报都需要有一个源点。由于我们是发送数据而不是接收数据,我们
    将地址初始化伟0,并且让OS来为我们选择一个端口。我们也可以选择1025到
    65535之间的没有被使用的任意端口。    
     
        The biggest difference between client and server when datagrams
        are used is the fact that servers tend to have a known/fixed
        address at which they listen and clients tend to have arbitrary
    addresses assigned by the OS. 
    客户端与服务器端的最大的不同是服务器端的数据报是监听一个众所周知/
    固定的地址,而客户端倾向于使用OS分配的地址。 
    */
      ACE_INET_Addr local((u_short) 0);
     
      /* And here is our datagram object. 
     这是我们的数据报对象
    */
      ACE_SOCK_Dgram dgram;
     
      /* Notice that this looks a lot like the server application.
        There's no difference in creating server datagrams an client
        datagrams.  You can even use a zero-constructed address for your
        server datagram as long as you tell the client where you're
    listening (eg -- by writting into a file or some such). 
    注意这和服务器端的应用有很多相同的地方。在客户端创建数据报是和服务
    器端创建数据报没有什么不同。只要你能告诉客户端你监听的端口(例如 
    把端口号写到文件里面),你就可以向服务器端的数据包传入一个空值的地址。 
    */
      if (dgram.open (local) == -1)
        ACE_ERROR_RETURN ((LM_ERROR,
                           "%p\n",
                           "datagram open"),
                          -1);
     
      /* Yep.  We've seen this before too... 
       这和我们以前看到的一样 
    */
      char buf[BUFSIZ];
     
      /* Ok, now we're doing something different. 
      现在我们做一些不同的事情 
    */
      sprintf (buf, "Hello World!");
     
      /* Just like sending a telegram, we have to address our datagram.
        Here, we create an address object at the desired port on the
        chosen host.  To keep us from crashing, we'll provide a default
    host name if we aren't given one.
    和发送电报一样,我们也需要指定我们的发送地址。这里我们为我们选定的
    主机指定的端口创建一个地址对象。为了防止程序崩溃,如果没有选定主机地址
    我们需要提供一个缺省的主机,  
    */
      ACE_INET_Addr remote (PORT,
                            argc > 1 ? argv[1] : "localhost");
     
      ACE_DEBUG ((LM_DEBUG,
                  "(%P|%t) Sending (%s) to the server.\n",
                  buf));
      /* Now we send our buffer of stuff to the remote address.  This is
        just exactly what the server did after receiving a client message.
        Datagrams are rather orthogonal that way: they don't generally
    make much of a fuss about being either client or server.  
    现在我们把buffer的数据发送到远端的地址去。这和服务器接收到客户端的
    发送的数据一样的处理方法,对于数据报来说,服务器和客户端基本没有区别。
    */
      if (dgram.send (buf,
                      ACE_OS::strlen (buf) + 1,
                      remote) == -1)
        ACE_ERROR_RETURN ((LM_ERROR,
                           "%p\n",
                           "send"),
                          -1);
     
      /* Now we've turned around and put ourselves into "server mode" by
        invoking the recv() method.  We know our server is going to send
        us something, so we hang out here and wait for it.  Because we
        know datagrams are unreliable, there is a chance that the server
        will respond but we won't hear.  You might consider providing a
        timeout on the recv() in that case.  If recv() fails due to
        timeout it will return -1 and you can then resend your query and
        attempt the recv() again.
    现在通过调用recv()方法,我们需要转变角色到“服务模式”。我们知道
    服务器会给我们发送消息,所有我们阻塞在这里,等待服务器发送的消息。
    因为我们知道数据报是不可靠的,服务器发送过来的消息,我们有可能会
    接收不到。你也许会考虑让recv()提供一个一个超时参数。 如果recv()
    由于超时返回失败,他将会返回一个-1,你可以可以重新发送一个你的请求,
    再尝试接收一次。
        Like the server application, we have to give the recv() an
        uninitialized addr object so that we can find out who is talking
    back to us. 
    和服务应用一样,我们需要给recv()指定一个没有初始化的地址对象,这样
    我们就可以知道谁回应我们的消息了。
     */
      if (dgram.recv (buf,
                      sizeof (buf),
                      remote) == -1)
        ACE_ERROR_RETURN ((LM_ERROR,
                           "%p\n",
                           "recv"),
                          -1);
     
      /* Find out what the server had to say.  
       显示服务器返回的消息
    */
      ACE_DEBUG ((LM_DEBUG,
                  "(%P|%t) The server said:  %s\n",
                  buf));
     
      /* Using the "remote" object instance, find out where the server
        lives.  We could then save this address and use directed datagrams
    to chat with the server for a while.  
      使用remote 对象实例,显示服务器的地址。 接下来我们可以将这个地址保存,
      然后通过数据报直接和服务器进行对话。
    */
      ACE_DEBUG ((LM_DEBUG,
                  "(%P|%t) The server can be found at:  (%s:%d)\n",
                  remote.get_host_name(),
                  PORT));
     
      return 0;
    }

    这就这么简单明了,但是现阶段我们所做只是和我们知道的服务器进行对话,但是没能发现我们未知的服务器。现在你可以之间发送数据报到你网络中任何主机,但是这不是最佳的解决方案。再下一页,我们将向你展示正确的做法。


    收藏到:Del.icio.us