summaryrefslogtreecommitdiff
path: root/docs/tutorials/015/page16.html
blob: 620950ad5487d4791e59f00402885238f9ea1a08 (plain)
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<HTML>
<HEAD>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
   <META NAME="Author" CONTENT="James CE Johnson">
   <TITLE>ACE Tutorial 015</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">

<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER>

<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER>

<P>
<HR WIDTH="100%">
Recv is the sibling to Xmit.  Again, they could be combined into a
single object if you want.
<P>
An ACE_Stream is designed to handle downstream traffic very
well.  You put() data into it and it flows along towards the tail.
However, there doesn't seem to be a way to put data in such that it
will travel upstream.  To get around that, I've added a get() method
to Recv that will trigger a read on the socket.  Recv will then put
the data to the next upstream module and we're on our way.  As noted
earlier, that data will eventually show up either in the <i>reader</i> 
(if installed on the stream open()) or the stream head reader task's
message queue.
<HR>
<PRE>

<font color=red>// $Id$</font>

<font color=blue>#ifndef</font> <font color=purple>RECV_H</font>
<font color=blue>#define</font> <font color=purple>RECV_h</font>

<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>"

class ACE_SOCK_Stream;

<font color=red>/* Get some data from the peer and send it upstream for
   de-protocol-ization.
*/</font>
class Recv : public Protocol_Task
{
public:

    typedef Protocol_Task inherited;

     <font color=red>// Give it someone to talk to...</font>
    Recv( ACE_SOCK_Stream & _peer );

    ~Recv(void);

     <font color=red>// Trigger a read from the socket</font>
    int get(void);

     <font color=red>// In some cases it might be easier to check the "<font color=green>state</font>" of the</font>
     <font color=red>// Recv object than to rely on return codes filtering back to</font>
     <font color=red>// you.</font>
    int error(void)
        {
            return this->error_;
        }

protected:

    ACE_SOCK_Stream & peer(void)
        {
            return this->peer_;
        }

     <font color=red>// The baseclass will trigger this when our get() method is</font>
     <font color=red>// called.  A message block of the appropriate size is created,</font>
     <font color=red>// filled and passed up the stream.</font>
    int recv(ACE_Message_Block * message,
             ACE_Time_Value *timeout = 0);

private:
     <font color=red>// Our endpoint</font>
    ACE_SOCK_Stream & peer_;

     <font color=red>// get() uses a bogus message block to cause the baseclass to</font>
     <font color=red>// invoke recv().  To avoid memory thrashing, we create that</font>
     <font color=red>// bogus message once and reuse it for the life of Recv.</font>
    ACE_Message_Block * tickler_;

     <font color=red>// Our error flag (duh)</font>
    int error_;
};

<font color=blue>#endif</font> <font color=red>// RECV_H</font>
</PRE>
<P><HR WIDTH="100%">
<CENTER>[<A HREF="..">Tutorial Index</A>] [<A HREF="page17.html">Continue This Tutorial</A>]</CENTER>