~ubuntu-branches/ubuntu/oneiric/libjboss-remoting-java/oneiric

« back to all changes in this revision

Viewing changes to docs/Multiplex/multiplex.html

  • Committer: Package Import Robot
  • Author(s): Torsten Werner
  • Date: 2011-09-09 14:01:03 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: package-import@ubuntu.com-20110909140103-hqokx61534tas9rg
Tags: 2.5.3.SP1-1
* Newer but not newest upstream release. Do not build samples.
* Change debian/watch to upstream's svn repo.
* Add patch to fix compile error caused by tomcat update.
  (Closes: #628303)
* Switch to source format 3.0.
* Switch to debhelper level 7.
* Remove useless Depends.
* Update Standards-Version: 3.9.2.
* Update README.source.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<html><head><META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>The Multiplex Subsystem of the JBoss Remoting Project</title><meta content="DocBook XSL Stylesheets V1.69.1" name="generator"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="article" lang="en"><div class="titlepage"><div><div><h1 class="title"><a name="N10001"></a>The Multiplex Subsystem of the JBoss Remoting Project</h1></div><div><div class="author"><h3 class="author"><span class="firstname">Ron</span> <span class="surname">Sigal</span></h3></div></div><div><p class="releaseinfo">November 5, 2005</p></div><div><p class="copyright">Copyright &copy; 2005 Ron Sigal</p></div></div><div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#N1001D">Introduction.</a></span></dt><dt><span class="section"><a href="#N10049">The Prime Scenario.</a></span></dt><dt><span class="section"><a href="#N1011F">Virtual socket groups.</a></span></dt><dt><span class="section"><a href="#N102A7">Coding the Prime Scenario.</a></span></dt><dt><span class="section"><a href="#N10325">More general scenarios.</a></span></dt><dd><dl><dt><span class="section"><a href="#N1032A">The <span class="emphasis"><em>N</em></span>-socket scenario.</a></span></dt><dt><span class="section"><a href="#N1038B">The Symmetric Scenario.</a></span></dt></dl></dd><dt><span class="section"><a href="#N10425">Factories.</a></span></dt><dt><span class="section"><a href="#N10455">Performance.</a></span></dt><dt><span class="section"><a href="#N10514">APIs</a></span></dt><dt><span class="section"><a href="#N108DB">Issues.</a></span></dt><dt><span class="section"><a href="#N108E3">Listings.</a></span></dt></dl></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="N1001D"></a>Introduction.</h2></div></div><div></div></div><p>The Multiplex subsystem of the JBoss Remoting Project 
 
2
    (referred to herein on occasion simply as &ldquo;Muliplex&rdquo;) supports the 
 
3
    multiplexing of multiple data streams over a single network 
 
4
    connection, based on a reimplementation of the following classes from 
 
5
    <code class="code">java.net</code>:</p><div class="orderedlist"><ol type="1"><li><p><code class="classname">Socket</code></p></li><li><p><code class="classname">ServerSocket</code></p></li><li><p><code class="classname">SocketInputStream</code></p></li><li><p><code class="classname">SocketOutputStream</code></p></li></ol></div><p>and the following classes from <code class="code">javax.net:</code></p><div class="orderedlist"><ol type="1"><li><p><code class="classname">SocketFactory</code></p></li><li><p><code class="classname">ServerSocketFactory</code></p></li></ol></div><p>It is motivated by circumstances in which the number of 
 
6
    available ports on a system is restricted by a firewall or other 
 
7
    considerations. Since the Remoting project is the principal client 
 
8
    of Multiplex, we illustrate multiplexing primarily in the context 
 
9
    of a Remoting application. Remoting supports two modes of 
 
10
    client-server communication: (1) method calls from client to 
 
11
    server, with a synchronous response, and (2) client requests for an 
 
12
    asynchronous callback from the server. The usual need for separate 
 
13
    ports to support both synchronous and asynchronous modes is 
 
14
    obviated by the Multiplexing subsystem.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="N10049"></a>The Prime Scenario.</h2></div></div><div></div></div><p>The typical application of multiplexing in the Remoting 
 
15
    context is illustrated by the <span class="bold"><strong>Prime 
 
16
    Scenario</strong></span>, in which a client requiring both synchronous 
 
17
    and asynchronous responses from a server is behind a firewall and 
 
18
    has only a single port at its disposal. Without the restriction to 
 
19
    a single port, we would have the situation in <a href="#figure:1">Figure 1</a>, which 
 
20
    requires no multiplexing. With the restriction, we have the Prime 
 
21
    Scenario, as in <a href="#figure:2">Figure 2</a>.</p><div class="informalfigure"><a name="figure:1"></a><div class="mediaobject"><img src="images/figure_1.jpg"><div class="caption"><p>
 
22
               <span class="bold"><strong>
 
23
                  Figure 1.
 
24
               </strong></span>
 
25
               Method calls and callbacks with no port restrictions.</p></div></div></div><div class="informalfigure"><a name="figure:2"></a><div class="mediaobject"><img src="images/figure_2.jpg"><div class="caption"><p>
 
26
               <span class="bold"><strong>
 
27
                  Figure 2.
 
28
               </strong></span>
 
29
               Method calls and callbacks in the Prime Scenario.
 
30
            </p></div></div></div><p>Multiplexing is supported primarily by the concept of the 
 
31
    <span class="bold"><strong>virtual socket</strong></span>, implemented by the 
 
32
    <code class="classname">VirtualSocket</code> class. 
 
33
    <code class="classname">VirtualSocket</code> is a subclass of 
 
34
    <code class="classname">java.io.Socket</code>, and supports the full socket 
 
35
    API. As is the case with actual sockets, virtual sockets are 
 
36
    created in one of two ways:</p><div class="orderedlist"><ol type="1"><li><p>a constructor (or factory) call on a client, or</p></li><li><p>a call to the <code class="methodname">accept()</code> method of a server 
 
37
        socket on a server.</p></li></ol></div><p>Accordingly, the other principal Multiplex concept is the 
 
38
    <span class="bold"><strong>virtual server socket</strong></span>, implemented 
 
39
    by two classes:</p><div class="orderedlist"><ol type="1"><li><p><code class="classname">MultiPortVirtualServerSocket</code>, 
 
40
        and</p></li><li><p><code class="classname">SinglePortVirtualServerSocket</code>.</p></li></ol></div><p>These are both subclasses of 
 
41
    <code class="classname">java.io.ServerSocket</code>, and both implement the 
 
42
    full server socket API. Since virtual sockets are implemented on 
 
43
    the foundation of actual sockets, and the creation of actual 
 
44
    sockets requires a server socket, we need the support of actual 
 
45
    server sockets in the creation of virtual sockets. It is the role 
 
46
    of <code class="classname">MultiPortVirtualServerSocket</code> to provide 
 
47
    that support. The <code class="methodname">accept()</code> method of 
 
48
    <code class="classname">MultiPortVirtualServerSocket</code> calls 
 
49
    <code class="methodname">super.accept()</code> to create an actual socket which is 
 
50
    then wrapped in a mechanism which supports one or more virtual 
 
51
    sockets. Every Muliplex application requires at least one 
 
52
    <code class="classname">MultiPortVirtualServerSocket</code>, and the Prime 
 
53
    Scenario requires exactly one. <a href="#figure:3">Figure 3</a> illustrates the process in 
 
54
    which a virtual socket <span class="emphasis"><em>v1</em></span> connects to a 
 
55
    <code class="classname">MultiPortVirtualServerSocket</code>, which creates 
 
56
    and returns a reference to a new virtual socket 
 
57
    <span class="emphasis"><em>v2</em></span>.</p><div class="informalfigure"><a name="figure:3"></a><div class="mediaobject"><img src="images/figure_3.jpg"><div class="caption"><p>
 
58
               <span class="bold"><strong>
 
59
                  Figure 3.
 
60
               </strong></span>
 
61
               Setting up a synchronous connection.
 
62
            </p></div></div></div><p>In <a href="#figure:3">Figure 3</a> we have a connection between <span class="emphasis"><em>v1</em></span> and 
 
63
    <span class="emphasis"><em>v2</em></span>, which can support synchronous communication but 
 
64
    which offers nothing not provided by actual sockets. The support of 
 
65
    multiplexed callbacks, however, requires the use 
 
66
    of the other virtual server socket class, 
 
67
    <code class="classname">SinglePortVirtualServerSocket</code>. Unlike 
 
68
    <code class="classname">MultiPortVirtualServerSocket</code>, 
 
69
    <code class="classname">SinglePortVirtualServerSocket</code> does not 
 
70
    depend on superclass facilities, but rather it uses an ordinary client socket,
 
71
    with which implements its own 
 
72
    version of the <code class="methodname">accept()</code> method, able to create any 
 
73
    number of virtual sockets, all of which share a single port with 
 
74
    the <code class="classname">SinglePortVirtualServerSocket</code>. It is important to understand
 
75
    how its use of an actual socket determines the nature of a 
 
76
    <code class="classname">SinglePortVirtualServerSocket</code>.  Unlike a server socket, a client
 
77
    socket must be connected to another socket to function, and a
 
78
    <code class="classname">SinglePortVirtualServerSocket</code> has the same property.  It follows
 
79
    that a <code class="classname">SinglePortVirtualServerSocket</code> can process requests
 
80
    from just one host, the host to which its actual socket is connected.</p><p>The role of the <code class="classname">SinglePortVirtualServerSocket</code> is 
 
81
    illustrated in <a href="#figure:4">Figure 4</a>. A constructor (or factory method, which 
 
82
    calls a constructor) is called on the server to create virtual socket 
 
83
    <span class="emphasis"><em>v3</em></span> to support callbacks. The constructor sends a 
 
84
    connection request to the 
 
85
    <code class="classname">SinglePortVirtualServerSocket</code> on the client, 
 
86
    which creates new virtual socket <span class="emphasis"><em>v4</em></span> and sends back to 
 
87
    <span class="emphasis"><em>v3</em></span> a reference to <span class="emphasis"><em>v4</em></span>. At this point the 
 
88
    Prime Scenario is set up.</p><div class="informalfigure"><a name="figure:4"></a><div class="mediaobject"><img src="images/figure_4.jpg"><div class="caption"><p>
 
89
               <span class="bold"><strong>
 
90
                  Figure 4.
 
91
               </strong></span>
 
92
               Adding an asynchronous connection to <a href="#figure:3">Figure 3</a>.
 
93
            </p></div></div></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="N1011F"></a>Virtual socket groups.</h2></div></div><div></div></div><p>In order to understand the creation of structures like the 
 
94
       Prime Scenario and others described below, it is important to 
 
95
       understand the concept of a <span class="bold"><strong>virtual socket 
 
96
       group</strong></span>. A virtual socket group is a set of virtual 
 
97
       sockets, and zero or one 
 
98
       <code class="classname">SinglePortVirtualServerSocket</code>s, sharing a 
 
99
       single actual socket. We say that the socket group is <span class="emphasis"><em>based 
 
100
       on</em></span> its actual socket. Depending on the state of its 
 
101
       underlying actual socket and the nature of its peer socket group, if any,
 
102
       a socket group may be in one of three states. 
 
103
       Let <span class="emphasis"><em>G</em></span> be a socket group based on actual socket 
 
104
       <span class="emphasis"><em>S</em></span>. Then <span class="emphasis"><em>G</em></span> may be</p><div class="orderedlist"><ol type="1"><li><p><span class="bold"><strong>bound</strong></span>: <span class="emphasis"><em>S</em></span> is bound but 
 
105
        not connected, or</p></li><li><p><span class="bold"><strong>connected</strong></span>: <span class="emphasis"><em>S</em></span> is 
 
106
        connected to socket <span class="emphasis"><em>S'</em></span> and the socket group based on
 
107
        <span class="emphasis"><em>S'</em></span> does not contain a <code class="classname">SinglePortVirtualServerSocket</code>, or</p></li><li><p><span class="bold"><strong>joinable</strong></span>: <span class="emphasis"><em>S</em></span> is 
 
108
        connected to socket <span class="emphasis"><em>S'</em></span> and the socket group based on
 
109
        <span class="emphasis"><em>S'</em></span> does contain a <code class="classname">SinglePortVirtualServerSocket</code>.</p></li></ol></div><p>Although it is possible for a socket to be neither bound nor 
 
110
       connected, we do not consider a socket group to exist until its 
 
111
       underlying socket is at least bound to a local address. A connected or joinable
 
112
       socket group is said to be <span class="bold"><strong>visible</strong></span>, and a bound
 
113
       socket group is <span class="bold"><strong>invisible</strong></span>.  A socket group 
 
114
       is characterized by the pair of addresses</p><div class="blockquote"><blockquote class="blockquote"><p>(<span class="emphasis"><em>localAddress</em></span>, 
 
115
      <span class="emphasis"><em>remoteAddress</em></span>)</p></blockquote></div><p>where these are the local and remote addresses of the actual 
 
116
       socket underlying the socket group. <span class="emphasis"><em>localAddress</em></span> 
 
117
       may take the special form (*, <span class="emphasis"><em>port</em></span>), where the 
 
118
       wildcard value &ldquo;*&rdquo; denotes any hostname by which the local host is 
 
119
       known. Depending on the state of the socket group, 
 
120
       <span class="emphasis"><em>remoteAddress</em></span> may have the special value 
 
121
       <span class="emphasis"><em>undefined</em></span>, indicating that a connection has not 
 
122
       yet been established.</p><p>There are two ways of creating a new virtual socket group 
 
123
       or of joining an existing socket group: through a <span class="bold"><strong>
 
124
       binding action</strong></span> or a <span class="bold"><strong>connecting 
 
125
       action</strong></span>. A binding action is either</p><div class="orderedlist"><ol type="1"><li><p>a call to any of the 
 
126
        <code class="classname">SinglePortVirtualServerSocket</code> 
 
127
        constructors other than the default constructor (i.e., those with a
 
128
        port parameter), or</p></li><li><p>a call to a <code class="methodname">bind()</code> method in 
 
129
         <code class="classname">VirtualSocket</code> or
 
130
         <code class="classname">SinglePortVirtualServerSocket</code>.</p></li></ol></div><p>A connecting action belongs to one of five categories:</p><div class="orderedlist"><ol type="1"><li><p>a call to any <code class="classname">VirtualSocket</code> or
 
131
         <code class="classname">SinglePortVirtualServerSocket</code>
 
132
         constructor that requires a remote address (note that
 
133
         unlike <code class="classname">java.net.ServerSocket</code>,
 
134
         <code class="classname">SinglePortVirtualServerSocket</code> has a
 
135
         such a constructor),</p></li><li><p>a call to a <code class="methodname">connect()</code> method (again,
 
136
         <code class="classname">SinglePortVirtualServerSocket</code> has a nonstandard
 
137
         <code class="methodname">connect()</code> method),</p></li><li><p>a call to 
 
138
        <code class="methodname">SinglePortVirtualServerSocket.accept()</code>,</p></li><li><p>a call to 
 
139
        <code class="methodname">MultiPortVirtualServerSocket.accept()</code>, or</p></li><li><p>a call to 
 
140
        <code class="methodname">MultiPortVirtualServerSocket.acceptServerSocketConnection()</code>.</p></li></ol></div><p>Each binding action has an associated local address, and each 
 
141
       connecting action has an associated remote address and an optional 
 
142
       local address. For binding actions, and connecting actions in the 
 
143
       first two categories, the addresses are given explicitly in the 
 
144
       method call. For a a call to 
 
145
       <code class="methodname">SinglePortVirtualServerSocket.accept()</code>, the addresses 
 
146
       are those of the socket group to which the server socket belongs, and 
 
147
       for the two <code class="classname">MultiPortVirtualServerSocket</code> 
 
148
       methods, the addresses are those of the actual socket they 
 
149
       create.</p><p>Depending on their associated local and remote addresses and 
 
150
       on the socket groups that exist at the time of the action, a binding or 
 
151
       connecting action may have the effect of creating a new socket group or 
 
152
       adding a new member to an existing socket group. The rules are straightforward, 
 
153
       but there is one source of possible confusion, the 
 
154
       <a href="#accident">accidental connection problem</a> discussed below, 
 
155
       that must be guarded against. Let <span class="emphasis"><em>V</em></span> be a virtual 
 
156
       socket or virtual server socket undergoing either a binding or 
 
157
       connecting action.</p><div class="orderedlist"><ol type="1"><li><p><span class="bold"><strong>binding action rule</strong></span>: If 
 
158
           there are visible socket groups whose local address matches the 
 
159
           action's local address, then <span class="emphasis"><em>V</em></span> joins one of 
 
160
           them chosen at random. Otherwise, a new bound socket group is created and 
 
161
           <span class="emphasis"><em>V</em></span> joins it.</p></li><li><p><span class="bold"><strong>connecting action rule</strong></span>:</p><div class="orderedlist"><ol type="a"><li><p>For actions in the first two categories, where <span class="emphasis"><em>V</em></span>
 
162
               is a <code class="classname">VirtualSocket</code> (respectively, a
 
163
               <code class="classname">SinglePortVirtualServerSocket</code>):</p><div class="orderedlist"><ol type="i"><li><p>If the action has a remote address but no local address:</p><div class="orderedlist"><ol type="A"><li><p>If there are any joinable (resp., connected) socket groups with a matching 
 
164
                         remote address, then <span class="emphasis"><em>V</em></span> joins one of them 
 
165
                         chosen at random.</p></li><li><p>If there are no such socket groups, an attempt
 
166
                         is made to connect to a <span class="emphasis"><em>MultiPortVirtualServerSocket</em></span>
 
167
                         at the remote address, and if the attempt succeeds, a 
 
168
                         new socket group is created and <span class="emphasis"><em>V</em></span> joins it.</p></li></ol></div></li><li><div class="orderedlist"><p>If the action has both a local address and a remote address:</p><ol type="A"><li><p>If there is a joinable (resp., connected) socket group with matching 
 
169
                         addresses, then <span class="emphasis"><em>V</em></span> joins it</p></li><li><p>Otherwise, if the local address (in particular, its port) is currently 
 
170
                           in use, the action results in a <code class="classname">IOException</code>.</p></li><li><p>Otherwise, a new socket group <span class="emphasis"><em>G</em></span> is created and bound
 
171
                           to the local address.  Then an attempt
 
172
                            is made to connect to a <span class="emphasis"><em>MultiPortVirtualServerSocket</em></span>
 
173
                            at the remote address, and if the attempt succeeds, <span class="emphasis"><em>V</em></span>
 
174
                           joins <span class="emphasis"><em>G</em></span>.</p></li></ol></div></li></ol></div></li><li><p>For <code class="methodname">SinglePortVirtualServerSocket.accept()</code> calls, 
 
175
               the new virtual socket joins the socket group to which the 
 
176
               server socket belongs.</p></li><li><p>For <code class="methodname">MultiPortVirtualServerSocket.accept()</code> calls, a 
 
177
               new socket group is created with the new virtual socket as its 
 
178
               first member.</p></li><li><p>For 
 
179
            <code class="methodname">MultiPortVirtualServerSocket.acceptServerSocketConnection()</code> 
 
180
            calls, a new socket group with zero members is created.</p></li></ol></div></li></ol></div><p><span class="bold"><strong>NOTES:</strong></span></p><div class="orderedlist"><ol type="1"><li><p>A bound socket group is inaccessible to the connect action rules (which is why
 
181
            it is called "invisible").  The reason is to avoid a situation in which
 
182
            one virtual socket "highjacks" another virtual
 
183
            socket's group.  Suppose that virtual socket <span class="emphasis"><em>v1</em></span> binds itself to
 
184
            ("localhost", 5555), but before it gets a chance to connect to ("www.jboss.com", 6666),
 
185
            virtual socket <span class="emphasis"><em>v2</em></span> binds to ("localhost", 5555) and then connects to
 
186
            ("www.ibm.com", 7777).  Then when <span class="emphasis"><em>v1</em></span> tries to connect to
 
187
            ("www.jboss.com", 6666), the attempt fails.  This situation cannot occur because
 
188
            at the moment when <span class="emphasis"><em>v2</em></span> does its bind, <span class="emphasis"><em>v1</em></span>'s
 
189
            socket group is invisible and <span class="emphasis"><em>v2</em></span> is forced to create it own
 
190
            socket group.</p></li><li><p>
 
191
            The connecting action rules are different for <code class="classname">VirtualSocket</code> and
 
192
            <code class="classname">SinglePortVirtualServerSocket</code> (specifically, the former can join
 
193
            only joinable socket groups, while the later can join connected socket groups) because
 
194
            <code class="classname">VirtualSocket</code> needs a <code class="classname">SinglePortVirtualServerSocket</code>
 
195
            to create a peer virtual socket for it to connect to, and a 
 
196
            <code class="classname">SinglePortVirtualServerSocket</code> does not need such a peer.
 
197
         </p></li><li><p><a name="accident"></a><span class="bold"><strong>N.B.</strong></span> It is important to understand a 
 
198
          possible side effect of a binding action. When <span class="emphasis"><em>V</em></span> joins a 
 
199
          socket group through a binding action, it is possible that the group is already 
 
200
          connected. In this  case, a subsequent connecting action (in particular, a call to 
 
201
          <code class="methodname">connect()</code>) to any address other than the 
 
202
          socket group's remote address is invalid, leading to an 
 
203
          <code class="classname">IOException</code> with the message "socket is already 
 
204
          connected.". This is called the <span class="bold"><strong>accidental connection
 
205
          problem</strong></span>, and it is avoidable.  Both <code class="classname">VirtualSocket</code>
 
206
          and <code class="classname">SinglePortVirtualServerSocket</code> have constructors and
 
207
          nonstandard versions of the <code class="methodname">connect()</code> which accept both
 
208
          local and remote addresses.  These treat binding and connecting as a single
 
209
          atomic process.</p></li></ol></div><p>The socket group rules are illustrated in the following two sections.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="N102A7"></a>Coding the Prime Scenario.</h2></div></div><div></div></div><p>In order to set up the Prime Scenario, the following steps 
 
210
    are necessary (the socket names conform to <a href="#figure:4">Figure 4</a>):</p><div class="orderedlist"><ol type="1"><li><p>On the server, create a 
 
211
        <code class="classname">MultiPortVirtualServerSocket</code> and bind it 
 
212
        to port <span class="emphasis"><em>P</em></span>.</p></li><li><p>On the client, create a virtual socket <span class="emphasis"><em>v1</em></span> 
 
213
        and connect it to port <span class="emphasis"><em>P</em></span>.</p></li><li><p>Let <span class="emphasis"><em>Q</em></span> be the port on the client to which 
 
214
        <span class="emphasis"><em>v1</em></span> is bound. Create a 
 
215
        <code class="classname">SinglePortVirtualServerSocket</code> on the 
 
216
        client, bind it to <span class="emphasis"><em>Q</em></span>, and connect it to 
 
217
        <span class="emphasis"><em>P</em></span>.</p></li><li><p>On the server, create a virtual socket <span class="emphasis"><em>v3</em></span> 
 
218
        and connect it to port <span class="emphasis"><em>Q</em></span>.</p></li></ol></div><p>The Prime Scenario provides an example of creating socket groups. 
 
219
    In step 2, a socket group <span class="emphasis"><em>G1</em></span> is created on the client 
 
220
    through the construction of <span class="emphasis"><em>v1</em></span>. It enters the 
 
221
    connected state, bound to an arbitrary port <span class="emphasis"><em>Q</em></span> on the 
 
222
    client and connected to port <span class="emphasis"><em>P</em></span> on the server. In step 
 
223
    3 a <code class="classname">SinglePortVirtualServerSocket</code> joins 
 
224
    <span class="emphasis"><em>G1</em></span> by way of binding to <span class="emphasis"><em>Q</em></span> on the client 
 
225
    and connecting to <span class="emphasis"><em>P</em></span> on the server. In fact, the 
 
226
    socket group rules imply that it is enough to bind the server socket to 
 
227
    port <span class="emphasis"><em>Q</em></span>. Connecting it to <span class="emphasis"><em>P</em></span> on the server 
 
228
    occurs as a side effect of the binding action. Finally, step 4 adds 
 
229
    virtual socket <span class="emphasis"><em>v4</em></span> to <span class="emphasis"><em>G1</em></span>. While 
 
230
    <span class="emphasis"><em>G1</em></span> is being built on the client, a socket group 
 
231
    <span class="emphasis"><em>G2</em></span> is being built on the server. Step 2 results in the 
 
232
    creation of <span class="emphasis"><em>G2</em></span>, along with its first member, a new 
 
233
    virtual socket, <span class="emphasis"><em>v2</em></span>, returned by the 
 
234
    <code class="methodname">accept()</code> method of the 
 
235
    <code class="classname">MultiPortVirtualServerSocket</code>. Step 4 adds a 
 
236
    second member, <span class="emphasis"><em>v3</em></span>, to <span class="emphasis"><em>G2</em></span>.</p><p>See <a href="#listing:1">Listing 1</a> and <a href="#listing:2">Listing 2</a>
 
237
    for a simple example of coding these 
 
238
    steps. Variants of these samples may be found in the directory 
 
239
    /org/jboss/remoting/samples/multiplex.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="N10325"></a>More general scenarios.</h2></div></div><div></div></div><p>Although Multiplex was motivated by the Prime Scenario, it 
 
240
       can also support other connection structures. We describe two 
 
241
       alternatives in this section.</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="N1032A"></a>The <span class="emphasis"><em>N</em></span>-socket scenario.</h3></div></div><div></div></div><p>The <span class="bold"><strong><span class="emphasis"><em>N</em></span>-socket 
 
242
         scenario</strong></span> demonstrates that a socket group is not restricted 
 
243
         to just two virtual sockets. It also demonstrates that a 
 
244
         <code class="classname">SinglePortVirtualServerSocket</code> does not 
 
245
         depend on the prior existence of a connected virtual socket. As 
 
246
         long as it has access to a 
 
247
         <code class="classname">MultiPortVirtualServerSocket</code> ready to 
 
248
         accept a connection, it can get started. In fact, the 
 
249
         <code class="methodname">MultiPortVirtualServerSocket.accept()</code> method will 
 
250
         silently accept a connection from a 
 
251
         <code class="classname">SinglePortVirtualServerSocket</code> while it is 
 
252
         waiting for a connection request from a virtual socket, but the 
 
253
         <code class="methodname">acceptServerSocketConnection()</code> method is designed 
 
254
         specifically to accept a connection request from a 
 
255
         <code class="classname">SinglePortVirtualServerSocket</code>.</p><p>The connection structure of the 
 
256
         <span class="emphasis"><em>N</em></span>-socket scenario is depicted in <a href="#figure:5">Figure 5</a> 
 
257
         (for <span class="emphasis"><em>N</em></span> = 3), and the code for a simple 
 
258
         client and server is given in <a href="#listing:3">Listing 3</a> and
 
259
         <a href="#listing:4">Listing 4</a>. In the example a 
 
260
         socket group with 3 elements is constructed on the server. It is 
 
261
         created with the call</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
262
                  serverSocket.acceptServerSocketConnection()
 
263
              </pre></blockquote></div><p>which creates an actual socket and a socket group which, though 
 
264
         it has no members, is connected to a 
 
265
         <code class="classname">SinglePortVirtualServerSocket</code> on the 
 
266
         client. The next three lines,</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
267
                  Socket socket1 = new VirtualSocket(&ldquo;localhost&rdquo;, 5555);
 
268
                  Socket socket2 = new VirtualSocket(&ldquo;localhost&rdquo;, 5555);
 
269
                  Socket socket3 = new VirtualSocket(&ldquo;localhost&rdquo;, 5555);
 
270
              </pre></blockquote></div><p>populate the socket group with three virtual sockets. On the 
 
271
         client there is a socket group with four members, first created with 
 
272
         the call</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
273
                  serverSocket.connect(connectAddress);
 
274
            </pre></blockquote></div><p>and then further populated by the three subsequent 
 
275
         lines</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
276
                  Socket socket1 = serverSocket.accept();
 
277
                  Socket socket2 = serverSocket.accept();
 
278
                  Socket socket3 = serverSocket.accept();
 
279
            </pre></blockquote></div><p>Variants of the <span class="emphasis"><em>N</em></span>-Socket Scenario 
 
280
         client and server may be found in the directory 
 
281
         /org/jboss/remoting/samples/multiplex.</p><div class="informalfigure"><a name="figure:5"></a><div class="mediaobject"><img src="images/figure_5.jpg"><div class="caption"><p>
 
282
                     <span class="bold"><strong>
 
283
                        Figure 5.
 
284
                     </strong></span>
 
285
                     The connection structure in the <span class="emphasis"><em>N</em></span>-Socket Scenario.
 
286
                  </p></div></div></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="N1038B"></a>The Symmetric Scenario.</h3></div></div><div></div></div><p>The connection structure in the <span class="bold"><strong>
 
287
         Symmetric Scenario</strong></span> consists of socket groups on two hosts, 
 
288
         each of which contains a 
 
289
         <code class="classname">SinglePortVirtualServerSocket</code> and some 
 
290
         number of virtual sockets. The scenario is not truly symmetric, 
 
291
         since each connection structure has to begin with a connection 
 
292
         request to a <code class="classname">MultiPortVirtualServerSocket</code>, 
 
293
         but once that happens the &ldquo;client&rdquo; and &ldquo;server&rdquo; are identical, as 
 
294
         depicted in <a href="#figure:6d">Figure 6d</a>. Once the line</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
295
                  serverSocket.connect(address);
 
296
            </pre></blockquote></div><p>on the client (see <a href="#listing:5">Listing 5</a>) and the line</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
297
                  int port = mpvss.acceptServerSocketConnection();
 
298
            </pre></blockquote></div><p>on the server (see <a href="#listing:6">Listing 6</a>)
 
299
            are executed, the client has a socket group 
 
300
            characterized by the address pair</p><div class="blockquote"><blockquote class="blockquote"><p>((*, 5555), (&ldquo;localhost&ldquo;, 7777))</p></blockquote></div><p>and consisting of a 
 
301
         <code class="classname">SinglePortVirtualServerSocket</code>, and the 
 
302
         server has a socket group with zero members characterized by the 
 
303
         address pair</p><div class="blockquote"><blockquote class="blockquote"><p>((&ldquo;localhost&ldquo;, 7777), (&ldquo;localhost&rdquo;, 5555)).</p></blockquote></div><p>(See <a href="#figure:6a">Figure 6a</a>.) And once the line</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
304
                  spvss.connect(address);
 
305
            </pre></blockquote></div><p>is executed on the server, the new 
 
306
         <code class="classname">SinglePortVirtualServerSocket</code> joins the 
 
307
         server's socket group, as shown in <a href="#figure:6b">Figure 6b</a>. After the 
 
308
         lines</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
309
                  Socket virtualSocket1 = new VirtualSocket(&ldquo;localhost&rdquo;, port);
 
310
            </pre></blockquote></div><p>and</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
311
                  Socket virtualSocket1 = spvss.accept();
 
312
            </pre></blockquote></div><p>are executed on the client and server, respectively, each 
 
313
         socket group has a new virtual socket (see <a href="#figure:6c">Figure 6c</a>), and finally, 
 
314
         after the lines</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
315
                  Socket virtualSocket2 = new VirtualSocket(&ldquo;localhost&rdquo;, 5555);
 
316
            </pre></blockquote></div><p>and</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
317
                  Socket virtualSocket2 = serverSocket.accept();
 
318
            </pre></blockquote></div><p>are executed on the server and client, respectively, each 
 
319
         socket group has a second virtual socket (see <a href="#figure:6d">Figure 6d</a>).</p><div class="informalfigure"><a name="figure:6a"></a><div class="mediaobject"><img src="images/figure_6a.jpg"><div class="caption"><p>
 
320
                     <span class="bold"><strong>
 
321
                        Figure 6a.
 
322
                     </strong></span>
 
323
                     The connection structure in the Symmetric Scenario: stage 1.
 
324
                  </p></div></div></div><div class="informalfigure"><a name="figure:6b"></a><div class="mediaobject"><img src="images/figure_6b.jpg"><div class="caption"><p>
 
325
                     <span class="bold"><strong>
 
326
                        Figure 6b.
 
327
                     </strong></span>
 
328
                     The connection structure in the Symmetric Scenario: stage 2.
 
329
                  </p></div></div></div><div class="informalfigure"><a name="figure:6c"></a><div class="mediaobject"><img src="images/figure_6c.jpg"><div class="caption"><p>
 
330
                     <span class="bold"><strong>
 
331
                        Figure 6c.
 
332
                     </strong></span>
 
333
                     The connection structure in the Symmetric Scenario: stage 3.
 
334
                  </p></div></div></div><div class="informalfigure"><a name="figure:6d"></a><div class="mediaobject"><img src="images/figure_6d.jpg"><div class="caption"><p>
 
335
                     <span class="bold"><strong>
 
336
                        Figure 6d.
 
337
                     </strong></span>
 
338
                     The connection structure in the Symmetric Scenario: stage 4.
 
339
                  </p></div></div></div></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="N10425"></a>Factories.</h2></div></div><div></div></div><p>In addition to virtual sockets and virtual server sockets, 
 
340
      Multiplex also implements the two factories associated with 
 
341
      sockets: the socket factory and the server socket factory. 
 
342
      <code class="classname">VirtualSocketFactory</code> extends 
 
343
      <code class="classname">javax.net.SocketFactory</code> and reimplements all 
 
344
      of its methods. <code class="classname">VirtualServerSocketFactory</code> 
 
345
      extends <code class="classname">javax.net.ServerSocketFactory</code> and 
 
346
      reimplements all of its methods.<sup>[<a href="#ftn.N10436" name="N10436">1</a>]</sup> These two classes make it possible for a 
 
347
      section of code to be completely unaware that it is using virtual 
 
348
      sockets instead of actual sockets. The only configuration involved 
 
349
      in the use of these factories is the need to tell 
 
350
      <code class="classname">VirtualServerSocketFactory</code> whether it is 
 
351
      running on a client or a server, which tells it whether to create 
 
352
      <code class="classname">SinglePortVirtualServerSocket</code>s or 
 
353
      <code class="classname">MultiPortVirtualServerSocket</code>s, respectively. 
 
354
      That notification is performed by the methods 
 
355
      <code class="methodname">setOnClient()</code> and <code class="methodname">setOnServer()</code>. See 
 
356
      <a href="#listing:7">Listing 7</a> for an illustration of the idiomatic use of these 
 
357
      classes, where the method <code class="methodname">useFactories()</code> refers only 
 
358
      to the parent classes <code class="classname">SocketFactory</code> and 
 
359
      <code class="classname">ServerSocketFactory</code>.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="N10455"></a>Performance.</h2></div></div><div></div></div><p>It should come as no surprise that the classes in Muliplex 
 
360
      perform more slowly than their non-virtual counterparts, since the 
 
361
      multiplexing of data streams requires extra work. Multiplex uses 
 
362
      two classes to perform input and output multiplexing: 
 
363
      <code class="classname">MultiplexingInputStream</code> and 
 
364
      <code class="classname">MultiplexingOutputStream</code>, which are returned 
 
365
      by the <code class="classname">VirtualSocket</code> methods 
 
366
      <code class="methodname">getInputStream()</code> and <code class="methodname">getOutputStream()</code>, 
 
367
      respectively. These classes subclass 
 
368
      <code class="classname">java.io.InputStream</code> and 
 
369
      <code class="classname">java.io.OutputStream</code> and reimplement all of 
 
370
      their methods. Tests show that input/output by these classes is 
 
371
      roughly four to five times slower than input/output by their 
 
372
      counterpart classes used by actual sockets, 
 
373
      <code class="classname">java.net.SocketInputStream</code> and 
 
374
      <code class="classname">java.net.SocketOutputStream</code>. This 
 
375
      information is gathered from multiple runs of three tests:</p><div class="informaltable"><table border="1"><colgroup><col><col></colgroup><tbody><tr><td>
 
376
                     <p><span class="bold"><strong>bare  input</strong></span>:</p>
 
377
                  </td><td>
 
378
                     <p>compares the transmission of bytes from a 
 
379
                         <code class="classname">SocketOutputStream</code> to a 
 
380
                         <code class="classname">MultiplexingInputStream</code> with the 
 
381
                         transmission of bytes from a 
 
382
                         <code class="classname">SocketOutputStream</code> to a 
 
383
                         <code class="classname">SocketInputStream</code></p>
 
384
                  </td></tr><tr><td>
 
385
                     <p><span class="bold"><strong>bare 
 
386
                         output</strong></span>:</p></td><td><p>compares the 
 
387
                         transmission of bytes from a 
 
388
                         <code class="classname">MultiplexingOutputStream</code> to a 
 
389
                         <code class="classname">SocketInputStream</code> with the 
 
390
                         transmission of bytes from a 
 
391
                         <code class="classname">SocketOutputStream</code> to a 
 
392
                         <code class="classname">SocketInputStream</code></p>
 
393
                  </td></tr><tr><td>
 
394
                     <p><span class="bold"><strong>socket 
 
395
                         input/output</strong></span>:</p></td><td><p>compares 
 
396
                         the transmission of bytes from a 
 
397
                        <code class="classname">MultiplexingOutputStream</code> to a 
 
398
                        <code class="classname">MultiplexingInputStream</code> with the 
 
399
                         transmission of bytes from a 
 
400
                         <code class="classname">SocketOutputStream</code> to a 
 
401
                         <code class="classname">SocketInputStream</code></p>
 
402
                  </td></tr></tbody></table></div><p>Each of these tests was run 10 times, transmitting 100,000 
 
403
      bytes each time. <a href="#table:1">Table 1</a> gives the factor by which the virtual 
 
404
      socket version of each test was slower than the actual socket 
 
405
      version.</p><div class="table"><a name="table:1"></a><p class="title"><b>Table&nbsp;1.&nbsp;Factors by which virtual socket input/output is slower 
 
406
            than actual socket input/output.</b></p><table summary="Factors by which virtual socket input/output is slower 
 
407
            than actual socket input/output." border="1"><colgroup><col><col><col><col></colgroup><thead><tr><th>
 
408
                     <p></p>
 
409
                  </th><th>
 
410
                     <p>bare input</p>
 
411
                  </th><th>
 
412
                     <p>bare output</p>
 
413
                  </th><th>
 
414
                     <p>socket input/output</p>
 
415
                  </th></tr></thead><tbody><tr><td>
 
416
                     <p>minimum:</p>
 
417
                  </td><td>2.25</td><td>1.63</td><td>3.19</td></tr><tr><td>
 
418
                     <p>mean:</p>
 
419
                  </td><td>3.50</td><td>2.80</td><td>4.77</td></tr><tr><td>
 
420
                     <p>maximum:</p>
 
421
                  </td><td>4.42</td><td>4.67</td><td>8.58</td></tr></tbody></table></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="N10514"></a>APIs</h2></div></div><div></div></div><p>One of the design goals of Multiplex is to make virtual sockets and their related classes as
 
422
         indistinguishable as possible from their real counterparts. There are two areas in which
 
423
         Multiplex is detectibly different.</p><div class="orderedlist"><ol type="1"><li><p>The use of the two types of virtual server sockets entails an extra degree of complexity in
 
424
               setting up a multiplexed connection.</p></li><li><p>There are performance differences.</p></li></ol></div><p>On the other hand, the virtual classes implement complete APIs, so that once a connection is
 
425
         established, a <code class="classname">VirtualSocket</code>, for example, can be passed to a method in place of a
 
426
         <code class="classname">Socket</code> and will demonstrate the same behavior.  Similarly, 
 
427
         <code class="classname">MultiplexingInputStream</code>s and <code class="classname">MultiplexingOutputStream</code>s
 
428
         are functionally indistinguishable from <code class="classname">SocketInputStream</code>s and
 
429
         <code class="classname">SocketOutputStream</code>s.</p><p>It may be useful, however, to be aware of some implementational differences between the two sets
 
430
         of classes.  The public methods in the virtual classes can be placed in five categories.</p><div class="orderedlist"><ol type="1"><li><p>methods implemented directly by the class</p></li><li><p>methods inherited from the real superclass</p></li><li><p>methods implemented by delegation to the underlying real socket</p></li><li><p>methods whose behavior is essentially null (though they may throw an
 
431
               <code class="classname">IOException</code> if called on a closed virtual socket)</p></li><li><p>methods which have no counterpart in the real class</p></li></ol></div><p>Categories 3, 4, and 5 are particularly informative.  Methods in category 3 can be used to
 
432
         fine tune a multiplexed connection by, for example, adjusting buffer sizes.  Note that a method
 
433
         such as <code class="methodname">setReceiveBufferSize()</code> may be called on any virtual socket
 
434
         in a socket group with the same effect as calling it on any other virtual socket in the same group.
 
435
         Methods in category 4
 
436
         represent behavior that is not relevant to virtual sockets, and methods in category 5 represent
 
437
         behavior that is specific to the special nature of multiplexed connections.  The category 5
 
438
         version of <code class="methodname">VirtualSocket.connect()</code>,</p><div class="blockquote"><blockquote class="blockquote"><pre class="programlisting">
 
439
               connect(SocketAddress remoteAddress, SocketAddress localAddress, int timeout)
 
440
         </pre></blockquote></div><p>exists to effect an atomic binding/connecting action to avoid the 
 
441
         <a href="#accident">accidental connection problem</a>
 
442
         discussed in the section on virtual socket groups. The notion of connection is irrelevant to ordinary
 
443
         server sockets, but <code class="classname">SinglePortVirtualServerSocket</code> has methods</p><div class="blockquote"><blockquote class="blockquote"><p>
 
444
            <pre class="programlisting">
 
445
                connect(SocketAddress remoteAddress, SocketAddress localAddress, int timeout)
 
446
            </pre>
 
447
         </p></blockquote></div><p>and <code class="methodname">isConnected()</code> because a 
 
448
         connection must be established before <code class="methodname">accept()</code> can function.</p><p>We also include in category 5 one of <code class="classname">SinglePortVirtualServerSocket</code>'s
 
449
         nonstandard constructors, with the signature</p><div class="blockquote"><blockquote class="blockquote"><p>
 
450
            <pre class="programlisting">
 
451
               SinglePortVirtualServerSocket(InetSocketAddress remoteAddress, InetSocketAddress localAddress, int timeout)
 
452
            </pre>
 
453
         </p></blockquote></div><p>
 
454
        which calls the two-address form of <code class="methodname">connect()</code>.</p><p>The public methods of the main Multiplex classes are categorized in <a href="#table:2">Table 2</a>.
 
455
         and <a href="#table:3">Table 3</a>. The only inherited methods among the
 
456
         classes listed in <a href="#table:2">Table 2</a>
 
457
         are found in <code class="classname">MultiPortVirtualServerSocket</code>, and
 
458
         we omit an explicit listing of them.</p><div class="table"><a name="table:2"></a><p class="title"><b>Table&nbsp;2.&nbsp;Categories of public methods in the primary public Multiplex classes</b></p><table summary="Categories of public methods in the primary public Multiplex classes" border="1"><colgroup><col align="center"><col><col><col></colgroup><thead><tr><th align="center">
 
459
                     <p></p>
 
460
                  </th><th>
 
461
                     <p><code class="classname">VirtualSocket</code></p>
 
462
                  </th><th>
 
463
                     <p><code class="classname">SinglePortVirtualServerSocket</code></p>
 
464
                  </th><th>
 
465
                     <p><code class="classname">MultiPortVirtualServerSocket</code></p>
 
466
                  </th></tr></thead><tbody><tr><td rowspan="14" align="center" valign="middle">
 
467
                     <p><span class="bold"><strong>category 1</strong></span></p>
 
468
                  </td><td><p><code class="methodname">bind()</code></p></td><td><p><code class="methodname">accept()</code></p></td><td><p><code class="methodname">accept()</code></p></td></tr><tr><td><p><code class="methodname">close()</code></p></td><td><p><code class="methodname">bind()</code></p></td><td><p><code class="methodname">toString()</code></p></td></tr><tr><td><p><code class="methodname">connect()</code></p></td><td><p><code class="methodname">close()</code></p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">getInputStream()</code></p></td><td><p><code class="methodname">getSoTimeout()</code></p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">getOutputStream()</code></p></td><td><p><code class="methodname">isBound()</code></p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">getSoTimeout()</code></p></td><td><p><code class="methodname">isClosed()</code></p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">isClosed()</code></p></td><td><p><code class="methodname">setSoTimeout()</code></p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">isConnected()</code></p></td><td><p><code class="methodname">toString()</code></p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">isInputShutdown()</code></p></td><td><p> </p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">isOutputShutdown()</code></p></td><td><p> </p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">setSoTimeout()</code></p></td><td><p> </p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">shutdownInput()</code></p></td><td><p> </p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">shutdownOutput()</code></p></td><td><p> </p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">toString()</code></p></td><td><p> </p></td><td><p> </p></td></tr><tr><td align="center"><p> </p></td><td><p> </p></td><td><p> </p></td><td><p> </p></td></tr><tr><td rowspan="13" align="center" valign="middle">
 
469
                     <p><span class="bold"><strong>category 3</strong></span></p>
 
470
                  </td><td><p><code class="methodname">getInetAddress()</code></p></td><td><p><code class="methodname">getInetAddress()</code></p></td><td><p> </p></td></tr><tr><td>
 
471
                     <p> 
 
472
                        <code class="methodname">getKeepAlive()</code>/<code class="methodname">setKeepAlive()</code></p>
 
473
                  </td><td><p><code class="methodname">getLocalPort()</code></p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">getLocalAddress()</code></p></td><td><p><code class="methodname">getLocalSocketAddress()</code></p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">getLocalPort()</code></p></td><td>
 
474
                     <p> 
 
475
                        <code class="methodname">getReceiveBufferSize()</code>/<code class="methodname">setReceiveBufferSize()</code></p>
 
476
                  </td><td><p> </p></td></tr><tr><td><p><code class="methodname">getLocalSocketAddress()</code></p></td><td>
 
477
                     <p> 
 
478
                        <code class="methodname">getReuseAddress()</code>/<code class="methodname">setReuseAddress()</code></p>
 
479
                  </td><td><p> </p></td></tr><tr><td><p><code class="methodname">getPort()</code></p></td><td><p> </p></td><td><p> </p></td></tr><tr><td>
 
480
                     <p> 
 
481
                        <code class="methodname">getReceiveBufferSize()</code>/<code class="methodname">setReceiveBufferSize()</code></p>
 
482
                  </td><td><p> </p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">getRemoteSocketAddress()</code></p></td><td><p> </p></td><td><p> </p></td></tr><tr><td>
 
483
                     <p> 
 
484
                        <code class="methodname">getReuseAddress()</code>/<code class="methodname">setReuseAddress()</code></p>
 
485
                  </td><td><p> </p></td><td><p> </p></td></tr><tr><td>
 
486
                     <p>
 
487
                        <code class="methodname">getSendBufferSize()</code>/<code class="methodname">setSendBufferSize()</code></p>
 
488
                  </td><td><p> </p></td><td><p> </p></td></tr><tr><td>
 
489
                     <p>
 
490
                        <code class="methodname">getSOLinger()</code>/<code class="methodname">setSOLinger()</code></p>
 
491
                  </td><td><p> </p></td><td><p> </p></td></tr><tr><td>
 
492
                     <p>
 
493
                        <code class="methodname">getTCPNoDelay()</code>/<code class="methodname">setTCPNoDelay()</code></p>
 
494
                  </td><td><p> </p></td><td><p> </p></td></tr><tr><td>
 
495
                     <p>
 
496
                        <code class="methodname">getTrafficClass()</code>/<code class="methodname">setTrafficClass()</code></p>
 
497
                  </td><td><p> </p></td><td><p> </p></td></tr><tr><td align="center"><p> </p></td><td><p> </p></td><td><p> </p></td><td><p> </p></td></tr><tr><td rowspan="3" align="center" valign="middle">
 
498
                     <p><span class="bold"><strong>category 4</strong></span></p>
 
499
                  </td><td><p><code class="methodname">getChannel()</code></p></td><td><p><code class="methodname">getChannel()</code></p></td><td><p> </p></td></tr><tr><td>
 
500
                     <p>
 
501
                        <code class="methodname">getOOBInline()</code>/<code class="methodname">setOOBInline()</code></p>
 
502
                  </td><td><p> </p></td><td><p> </p></td></tr><tr><td><p><code class="methodname">sendUrgentData()</code></p></td><td><p> </p></td><td><p> </p></td></tr><tr><td align="center"><p> </p></td><td><p> </p></td><td><p> </p></td><td><p> </p></td></tr><tr><td rowspan="3" align="center" valign="middle">
 
503
                     <p><span class="bold"><strong>category 5</strong></span></p>
 
504
                  </td><td>
 
505
                     <p><code class="methodname">connect()</code>
 
506
                        <sup>[<a href="#ftn.N107A4" name="N107A4">a</a>]</sup>
 
507
                        </p>
 
508
                  </td><td><p><code class="methodname">connect()</code></p></td><td><p><code class="methodname">acceptServerSocketConnection()</code></p></td></tr><tr><td><p></p></td><td><p><code class="methodname">isConnected()</code></p></td><td><p> </p></td></tr><tr><td><p></p></td><td>
 
509
                     <p><code class="methodname">SinglePortVirtualServerSocket()</code>
 
510
                        <sup>[<a href="#ftn.N107C7" name="N107C7">b</a>]</sup>
 
511
                        </p>
 
512
                  </td><td><p></p></td></tr></tbody><tbody class="footnotes"><tr><td colspan="4"><div class="footnote"><p><sup>[<a href="#N107A4" name="ftn.N107A4">a</a>] </sup>This version of <code class="methodname">connect()</code> is nonstandard
 
513
                              in that it has both a local and remote address.  It binds to
 
514
                              a local address and connects to a remote address in a single atomic action.</p></div><div class="footnote"><p><sup>[<a href="#N107C7" name="ftn.N107C7">b</a>] </sup>This constructor is nonstandard
 
515
                              in that it has both a local and remote address.  It binds to
 
516
                              a local address and connects to a remote address in a single atomic action.</p></div></td></tr></tbody></table></div><div class="table"><a name="table:3"></a><p class="title"><b>Table&nbsp;3.&nbsp;Categories of public methods in the other public Multiplex classes</b></p><table summary="Categories of public methods in the other public Multiplex classes" border="1"><colgroup><col align="center"><col><col><col><col></colgroup><thead><tr><th align="center">
 
517
                     <p></p>
 
518
                  </th><th>
 
519
                     <p><code class="classname">MultiplexingInputStream</code></p>
 
520
                  </th><th>
 
521
                     <p><code class="classname">MultiplexingOutputStream</code></p>
 
522
                  </th><th>
 
523
                     <p><code class="classname">VirtualServerSocketFactory</code></p>
 
524
                  </th><th>
 
525
                     <p><code class="classname">VirtualSocketFactory</code></p>
 
526
                  </th></tr></thead><tbody><tr><td rowspan="4" align="center" valign="middle">
 
527
                     <p><span class="bold"><strong>category 1</strong></span></p>
 
528
                  </td><td><p><code class="methodname">available()</code></p></td><td><p><code class="methodname">close()</code></p></td><td><p><code class="methodname">createServerSocket()</code></p></td><td><p><code class="methodname">createSocket()</code></p></td></tr><tr><td><p><code class="methodname">close()</code></p></td><td><p><code class="methodname">write()</code></p></td><td><p><code class="methodname">getDefault()</code></p></td><td><p><code class="methodname">getDefault()</code></p></td></tr><tr><td><p><code class="methodname">skip()</code></p></td><td><p></p></td><td><p></p></td><td><p></p></td></tr><tr><td><p><code class="methodname">read()</code></p></td><td><p></p></td><td><p> </p></td><td class="auto-generated">&nbsp;</td></tr><tr><td align="center"><p> </p></td><td><p> </p></td><td><p> </p></td><td><p> </p></td><td class="auto-generated">&nbsp;</td></tr><tr><td rowspan="3" align="center" valign="middle">
 
529
                     <p><span class="bold"><strong>category 2</strong></span></p>
 
530
                  </td><td><p><code class="methodname">mark()</code></p></td><td><p></p></td><td><p></p></td><td><p></p></td></tr><tr><td><p><code class="methodname">markSupported()</code></p></td><td><p></p></td><td><p></p></td><td><p></p></td></tr><tr><td><p><code class="methodname">reset()</code></p></td><td><p></p></td><td><p></p></td><td><p></p></td></tr><tr><td align="center"><p> </p></td><td><p> </p></td><td><p> </p></td><td><p> </p></td><td class="auto-generated">&nbsp;</td></tr><tr><td align="center" valign="middle">
 
531
                     <p><span class="bold"><strong>category 4</strong></span></p>
 
532
                  </td><td><p></p></td><td><p><code class="methodname">flush()</code></p></td><td><p></p></td><td><p></p></td></tr><tr><td align="center"><p> </p></td><td><p> </p></td><td><p> </p></td><td><p> </p></td><td class="auto-generated">&nbsp;</td></tr><tr><td rowspan="4" align="center" valign="middle">
 
533
                     <p><span class="bold"><strong>category 5</strong></span></p>
 
534
                  </td><td><p></p></td><td><p></p></td><td><p><code class="methodname">isOnClient()</code></p></td><td><p></p></td></tr><tr><td><p></p></td><td><p></p></td><td><p><code class="methodname">isOnServer()</code></p></td><td><p></p></td></tr><tr><td><p></p></td><td><p></p></td><td><p><code class="methodname">setOnClient()</code></p></td><td><p></p></td></tr><tr><td><p></p></td><td><p></p></td><td><p><code class="methodname">setOnServer()</code></p></td><td><p></p></td></tr></tbody></table></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="N108DB"></a>Issues.</h2></div></div><div></div></div><p>Please post issues and bugs to 
 
535
          <code class="uri">http://jira.jboss.com/jira/browse/JBREM-91</code>.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="N108E3"></a>Listings.</h2></div></div><div></div></div><div class="blockquote"><a name="listing:1"></a><blockquote class="blockquote"><div class="blockquote-title"><p><b>Listing 1. Client for Prime Scenario example.</b></p></div><pre class="programlisting">
 
536
               public class PrimeScenarioExampleClient
 
537
               { 
 
538
                  public void runPrimeScenario()
 
539
                  {
 
540
                     try {
 
541
                        // create a VirtualSocket and connect it to MultiPortVirtualServerSocket
 
542
                        Socket v1 = new VirtualSocket("localhost", 5555);
 
543
   
 
544
                        // do some asynchronous input in a separate thread
 
545
                        new AsynchronousThread(v1).start();
 
546
   
 
547
                        // do some synchronous communication
 
548
                        ObjectOutputStream oos = new ObjectOutputStream(v1.getOutputStream());
 
549
                        ObjectInputStream ois = new ObjectInputStream(v1.getInputStream());
 
550
                        oos.writeObject(new Integer(3)); 
 
551
                        Integer i1 = (Integer) ois.readObject();
 
552
                        v1.close();
 
553
                     }
 
554
                     catch (Exception e) {}
 
555
                  }
 
556
   
 
557
                  class AsynchronousThread extends Thread                                                                                                         
 
558
                  {
 
559
                     private Socket virtualSocket;
 
560
   
 
561
                     AsynchronousThread(Socket virtualSocket)
 
562
                     {
 
563
                        this.virtualSocket = virtualSocket;
 
564
                     }
 
565
                     
 
566
                     public void run()
 
567
                     {
 
568
                        try {
 
569
                           // create a SinglePortVirtualServerSocket that shares a port
 
570
                           // with virtualSocket (Note that it will be connected by virtue
 
571
                           // of joining a connected socket group.)
 
572
                           ServerSocket serverSocket
 
573
                              = new SinglePortVirtualServerSocket(virtualSocket.getLocalPort());
 
574
   
 
575
                           // create a VirtualSocket that shares a port with virtualSocket
 
576
                           serverSocket.setSoTimeout(10000);
 
577
                           Socket v4 = serverSocket.accept();
 
578
   
 
579
                           // get an object from the server
 
580
                           v4.setSoTimeout(10000);
 
581
                           ObjectInputStream ois = new ObjectInputStream(v4.getInputStream());
 
582
                           Object o = ois.readObject();
 
583
                           serverSocket.close();
 
584
                           v4.close();
 
585
                        }
 
586
                        catch (Exception e) {}
 
587
                     }
 
588
                  }
 
589
   
 
590
                  public static void main(String[] args)
 
591
                  {
 
592
                     new PrimeScenarioExampleClient().runPrimeScenario();
 
593
                  }
 
594
               }
 
595
         </pre></blockquote></div><div class="blockquote"><a name="listing:2"></a><blockquote class="blockquote"><div class="blockquote-title"><p><b>Listing 2. Server for Prime Scenario example.</b></p></div><pre class="programlisting">
 
596
               public class PrimeScenarioExampleServer
 
597
               {
 
598
                  public void runPrimeScenario()
 
599
                  {
 
600
                     try {
 
601
                        // create a MultiPortVirtualServerSocket and get a VirtualSocket
 
602
                        ServerSocket serverSocket = new MultiPortVirtualServerSocket(5555);
 
603
                        serverSocket.setSoTimeout(10000);
 
604
                        Socket v2 = serverSocket.accept();
 
605
      
 
606
                        // do some asynchronous communication in a separate thread
 
607
                        Thread asynchronousThread = new AsynchronousThread(v2);
 
608
                        asynchronousThread.start();
 
609
      
 
610
                        // do some synchronous communication
 
611
                        ObjectInputStream ois = new ObjectInputStream(v2.getInputStream());
 
612
                        ObjectOutputStream oos = new ObjectOutputStream(v2.getOutputStream());
 
613
                        v2.setSoTimeout(10000);
 
614
                        Object o = ois.readObject();
 
615
                        oos.writeObject(o);
 
616
      
 
617
                        serverSocket.close();
 
618
                        v2.close();
 
619
                     }
 
620
                     catch (Exception e) { }
 
621
                  }
 
622
      
 
623
                  class AsynchronousThread extends Thread
 
624
                  {
 
625
                     private Socket virtualSocket;
 
626
      
 
627
                     public AsynchronousThread(Socket socket) throws IOException
 
628
                     {this.virtualSocket = socket;}
 
629
      
 
630
                     public void run()
 
631
                     {
 
632
                        try {
 
633
                           // connect to SinglePortVirtualServerSocket
 
634
                           String hostName = virtualSocket.getInetAddress().getHostName();
 
635
                           int port = virtualSocket.getPort();
 
636
                           Socket v3 = new VirtualSocket(hostName, port);
 
637
      
 
638
                           // send an object to the client
 
639
                           ObjectOutputStream oos = new ObjectOutputStream(v3.getOutputStream());
 
640
                           oos.writeObject(new Integer(7));
 
641
      
 
642
                           oos.flush();
 
643
                           v3.close();
 
644
                        }
 
645
                        catch (Exception e) {}
 
646
                     }
 
647
                  }
 
648
      
 
649
                  public static void main(String[] args)
 
650
                  {
 
651
                     new PrimeScenarioExampleServer().runPrimeScenario();
 
652
                  }
 
653
               }
 
654
         </pre></blockquote></div><div class="blockquote"><a name="listing:3"></a><blockquote class="blockquote"><div class="blockquote-title"><p><b>Listing 3. Sample client for N-socket scenario.</b></p></div><pre class="programlisting">           
 
655
               public class N_SocketScenarioClient
 
656
               {
 
657
                  public void runN_SocketScenario()
 
658
                  {
 
659
                     try
 
660
                     {
 
661
                        // Create a SinglePortVirtualServerSocket and 
 
662
                        // connect it to the server.
 
663
                        SinglePortVirtualServerSocket serverSocket
 
664
                           = new SinglePortVirtualServerSocket(5555);
 
665
                        InetSocketAddress connectAddress
 
666
                           = new InetSocketAddress(&ldquo;localhost&rdquo;, 6666);
 
667
                        serverSocket.setSoTimeout(10000);
 
668
                        serverSocket.connect(connectAddress);
 
669
   
 
670
                        // Accept connection requests for 3 virtual sockets.
 
671
                        Socket socket1 = serverSocket.accept();
 
672
                        Socket socket2 = serverSocket.accept();
 
673
                        Socket socket3 = serverSocket.accept();
 
674
   
 
675
                        // Do some i/o.
 
676
                        InputStream is1 = socket1.getInputStream();
 
677
                        OutputStream os1 = socket1.getOutputStream();
 
678
                        InputStream is2 = socket2.getInputStream();
 
679
                        OutputStream os2 = socket2.getOutputStream();
 
680
                        InputStream is3 = socket3.getInputStream();
 
681
                        OutputStream os3 = socket3.getOutputStream();
 
682
                        os1.write(3);
 
683
                        os2.write(7);
 
684
                        os3.write(11);
 
685
                        System.out.println(is1.read());
 
686
                        System.out.println(is2.read());
 
687
                        System.out.println(is3.read());
 
688
   
 
689
                        socket1.close();
 
690
                        socket2.close();
 
691
                        socket3.close();
 
692
                        serverSocket.close();
 
693
                     }
 
694
                     catch (Exception e) {}
 
695
                  }
 
696
   
 
697
                  public static void main(String[] args)
 
698
                  {
 
699
                     new N_SocketScenarioClient().runN_SocketScenario();
 
700
                  }
 
701
               }
 
702
         </pre></blockquote></div><div class="blockquote"><a name="listing:4"></a><blockquote class="blockquote"><div class="blockquote-title"><p><b>Listing 4. Sample server for N-socket scenario.</b></p></div><pre class="programlisting">
 
703
               public class N_SocketScenarioServer
 
704
               {
 
705
                  public void runN_SocketScenario()
 
706
                  {
 
707
                     try
 
708
                     {
 
709
                        // Create and bind a MultiPortVirtualServerSocket.
 
710
                        MultiPortVirtualServerSocket serverSocket
 
711
                           = new MultiPortVirtualServerSocket(6666);
 
712
   
 
713
                        // Accept connection request from 
 
714
                        // SinglePortVirtualServerSocket.
 
715
                        serverSocket.setSoTimeout(10000);
 
716
                        serverSocket.acceptServerSocketConnection();
 
717
   
 
718
                        // Create 3 virtual sockets
 
719
                        Socket socket1 = new VirtualSocket("localhost", 5555);
 
720
                        Socket socket2 = new VirtualSocket("localhost", 5555);
 
721
                        Socket socket3 = new VirtualSocket("localhost", 5555);
 
722
   
 
723
                        // Do some i/o.
 
724
                        InputStream is1 = socket1.getInputStream();
 
725
                        OutputStream os1 = socket1.getOutputStream();
 
726
                        InputStream is2 = socket2.getInputStream();
 
727
                        OutputStream os2 = socket2.getOutputStream();
 
728
                        InputStream is3 = socket3.getInputStream();
 
729
                        OutputStream os3 = socket3.getOutputStream();
 
730
                        os1.write(is1.read());
 
731
                        os2.write(is2.read());
 
732
                        os3.write(is3.read());
 
733
   
 
734
                        socket1.close();
 
735
                        socket2.close();
 
736
                        socket3.close();
 
737
                        serverSocket.close();
 
738
                     }
 
739
                     catch (Exception e) {}
 
740
                  }
 
741
   
 
742
                  public static void main(String[] args)
 
743
                  {
 
744
                     new N_SocketScenarioServer().runN_SocketScenario();
 
745
                  }
 
746
               }
 
747
         </pre></blockquote></div><div class="blockquote"><a name="listing:5"></a><blockquote class="blockquote"><div class="blockquote-title"><p><b>Listing 5. Symmetric Scenario client.</b></p></div><pre class="programlisting">
 
748
               public class SymmetricScenarioClient
 
749
               {
 
750
                  public void runSymmetricScenario()
 
751
                  {
 
752
                     try {
 
753
                        // Get a virtual socket to use for synchronizing client and server.
 
754
                        Socket syncSocket = new Socket("localhost", 6666);
 
755
                        InputStream is_sync = syncSocket.getInputStream();
 
756
                        OutputStream os_sync = syncSocket.getOutputStream();
 
757
                       
 
758
                        // Create a SinglePortVirtualServerSocket and connect 
 
759
                        // it to MultiPortVirtualServerSocket running on the server.
 
760
                        SinglePortVirtualServerSocket serverSocket
 
761
                           = new SinglePortVirtualServerSocket(5555);
 
762
                        InetSocketAddress address = new InetSocketAddress("localhost", 7777);
 
763
                        is_sync.read();
 
764
                        serverSocket.setSoTimeout(10000);
 
765
                        serverSocket.connect(address);
 
766
                       
 
767
                        // Call constructor to create a virtual socket and make a connection
 
768
                        // request to the port on the server to which the local 
 
769
                        // SinglePortVirtualServerSocket is connected,
 
770
                        // i.e., to the remote SinglePortVirtualServerSocket.
 
771
                        os_sync.write(5);
 
772
                        is_sync.read();
 
773
                        int port = serverSocket.getRemotePort();
 
774
                        Socket virtualSocket1 = new VirtualSocket("localhost", port);
 
775
                        InputStream is1 = virtualSocket1.getInputStream();
 
776
                        OutputStream os1 = virtualSocket1.getOutputStream();
 
777
                       
 
778
                        // Create a virtual socket with SinglePortVirtualServerSocket.accept().
 
779
                        Socket virtualSocket2 = serverSocket.accept();
 
780
                        InputStream is2 = virtualSocket2.getInputStream();
 
781
                        OutputStream os2 = virtualSocket2.getOutputStream();
 
782
                       
 
783
                        // Do some i/o and close sockets.
 
784
                        os1.write(9);
 
785
                        System.out.println(is1.read());
 
786
                        os2.write(11);
 
787
                        System.out.println(is2.read());
 
788
                        virtualSocket1.close();
 
789
                        virtualSocket2.close();
 
790
                        syncSocket.close();
 
791
                        serverSocket.close();
 
792
                     }
 
793
                     catch (Exception e) {}
 
794
                  }
 
795
   
 
796
                  public static void main(String[] args)
 
797
                  {
 
798
                     new SymmetricScenarioClient().runSymmetricScenario();
 
799
                  }
 
800
               }
 
801
         </pre></blockquote></div><div class="blockquote"><a name="listing:6"></a><blockquote class="blockquote"><div class="blockquote-title"><p><b>Listing 6. Symmetric Scenario server.</b></p></div><pre class="programlisting">
 
802
               public class SymmetricScenarioServer
 
803
               {
 
804
                  public void runSymmetricScenario()
 
805
                  {
 
806
                     try {
 
807
                        // Create ServerSocket and get synchronizing socket.
 
808
                        ServerSocket ss = new ServerSocket(6666);
 
809
                        Socket syncSocket = ss.accept();
 
810
                        ss.close();
 
811
                        InputStream is_sync = syncSocket.getInputStream();
 
812
                        OutputStream os_sync = syncSocket.getOutputStream();
 
813
                           
 
814
                        // Create MultiPortVirtualServerSocket, accept connection request from remote
 
815
                        // SinglePortVirtualServerSocket, and get the bind port of the local actual
 
816
                        // socket to which the SinglePortVirtualServerSocket is connected. 
 
817
                        MultiPortVirtualServerSocket mpvss = new MultiPortVirtualServerSocket(7777);
 
818
                        os_sync.write(3);
 
819
                        mpvss.setSoTimeout(10000);
 
820
                        int port = mpvss.acceptServerSocketConnection();
 
821
                        mpvss.close();
 
822
                           
 
823
                        // Wait until remote SinglePortVirtualServerSocket is running, then create local
 
824
                        // SinglePortVirtualServerSocket, bind it to the local port to which the remote
 
825
                        // SinglePortVirtualServerSocket is connected, and connect it to the remote
 
826
                        // SinglePortVirtualServerSocket.
 
827
                        is_sync.read();
 
828
                        SinglePortVirtualServerSocket spvss = new SinglePortVirtualServerSocket(port);
 
829
                        InetSocketAddress address = new InetSocketAddress("localhost", 5555);
 
830
                        spvss.setSoTimeout(5000);
 
831
                        spvss.connect(address);
 
832
                           
 
833
                        // Indicate that the local SinglePortVirtualServerSocket is running.
 
834
                        os_sync.write(7);
 
835
                           
 
836
                        // Create a virtual socket by way of SinglePortVirtualServerSocket.accept();
 
837
                        serverSocket.setSoTimeout(10000);
 
838
                        Socket virtualSocket1 = spvss.accept();
 
839
                        InputStream is1 = virtualSocket1.getInputStream();
 
840
                        OutputStream os1 = virtualSocket1.getOutputStream();
 
841
                           
 
842
                        // Call constructor to create a virtual socket and make a connection
 
843
                        // request to the remote SinglePortVirtualServerSocket.
 
844
                        Socket virtualSocket2 = new VirtualSocket("localhost", 5555);
 
845
                        InputStream is2 = virtualSocket2.getInputStream();
 
846
                        OutputStream os2 = virtualSocket2.getOutputStream();
 
847
                           
 
848
                        // Do some i/o and close sockets.
 
849
                        os1.write(is1.read());
 
850
                        os2.write(is2.read());
 
851
                        virtualSocket1.close();
 
852
                        virtualSocket2.close();
 
853
                        syncSocket.close();
 
854
                        spvss.close();
 
855
                     }
 
856
                     catch (Exception e) {}
 
857
                  }
 
858
                           
 
859
                  public static void main(String[] args)
 
860
                  { 
 
861
                     new SymmetricScenarioServer().runSymmetricScenario();
 
862
                  }
 
863
               }
 
864
         </pre></blockquote></div><div class="blockquote"><a name="listing:7"></a><blockquote class="blockquote"><div class="blockquote-title"><p><b>Listing 7. Sample use of VirtualServerSocketFactory and VirtualSocketFactory.</b></p></div><pre class="programlisting">
 
865
               public class FactoryExample
 
866
               {
 
867
                  public void runFactoryExample()
 
868
                  {
 
869
                     ServerSocketFactory ssf = VirtualServerSocketFactory.getDefault();
 
870
                     ((VirtualServerSocketFactory) ssf).setOnServer();
 
871
                     SocketFactory sf = VirtualSocketFactory.getDefault();
 
872
                     useFactories(ssf, sf);
 
873
                  }
 
874
                       
 
875
                       
 
876
                  public void useFactories(ServerSocketFactory ssf, SocketFactory sf)
 
877
                  {
 
878
                     try
 
879
                     {
 
880
                        ServerSocket ss = ssf.createServerSocket(5555);
 
881
                        Socket s = sf.createSocket("localhost", 6666);
 
882
                     }
 
883
                     catch (Exception e)
 
884
                     {
 
885
                        e.printStackTrace();
 
886
                     }
 
887
                  }
 
888
                       
 
889
                       
 
890
                  public static void main(String[] args)
 
891
                  {
 
892
                     new FactoryExample().runFactoryExample();
 
893
                  }
 
894
               }
 
895
         </pre></blockquote></div></div><div class="footnotes"><br><hr align="left" width="100"><div class="footnote"><p><sup>[<a href="#N10436" name="ftn.N10436">1</a>] </sup>The methods that 
 
896
      require the backlog parameter are not implemented in the current 
 
897
      release.</p></div></div></div></body></html>
 
 
b'\\ No newline at end of file'