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 © 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 “Muliplex”) 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>
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>
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>
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>
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 “*” 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(“localhost”, 5555);
268
Socket socket2 = new VirtualSocket(“localhost”, 5555);
269
Socket socket3 = new VirtualSocket(“localhost”, 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>
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 “client” and “server” 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), (“localhost“, 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>((“localhost“, 7777), (“localhost”, 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(“localhost”, 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(“localhost”, 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>
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>
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>
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>
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>
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>
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>
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 1. 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>
414
<p>socket input/output</p>
415
</th></tr></thead><tbody><tr><td>
417
</td><td>2.25</td><td>1.63</td><td>3.19</td></tr><tr><td>
419
</td><td>3.50</td><td>2.80</td><td>4.77</td></tr><tr><td>
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)
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)
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 2. 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">
461
<p><code class="classname">VirtualSocket</code></p>
463
<p><code class="classname">SinglePortVirtualServerSocket</code></p>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
505
<p><code class="methodname">connect()</code>
506
<sup>[<a href="#ftn.N107A4" name="N107A4">a</a>]</sup>
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>
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 3. 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">
519
<p><code class="classname">MultiplexingInputStream</code></p>
521
<p><code class="classname">MultiplexingOutputStream</code></p>
523
<p><code class="classname">VirtualServerSocketFactory</code></p>
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"> </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"> </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"> </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"> </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
538
public void runPrimeScenario()
541
// create a VirtualSocket and connect it to MultiPortVirtualServerSocket
542
Socket v1 = new VirtualSocket("localhost", 5555);
544
// do some asynchronous input in a separate thread
545
new AsynchronousThread(v1).start();
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();
554
catch (Exception e) {}
557
class AsynchronousThread extends Thread
559
private Socket virtualSocket;
561
AsynchronousThread(Socket virtualSocket)
563
this.virtualSocket = virtualSocket;
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());
575
// create a VirtualSocket that shares a port with virtualSocket
576
serverSocket.setSoTimeout(10000);
577
Socket v4 = serverSocket.accept();
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();
586
catch (Exception e) {}
590
public static void main(String[] args)
592
new PrimeScenarioExampleClient().runPrimeScenario();
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
598
public void runPrimeScenario()
601
// create a MultiPortVirtualServerSocket and get a VirtualSocket
602
ServerSocket serverSocket = new MultiPortVirtualServerSocket(5555);
603
serverSocket.setSoTimeout(10000);
604
Socket v2 = serverSocket.accept();
606
// do some asynchronous communication in a separate thread
607
Thread asynchronousThread = new AsynchronousThread(v2);
608
asynchronousThread.start();
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();
617
serverSocket.close();
620
catch (Exception e) { }
623
class AsynchronousThread extends Thread
625
private Socket virtualSocket;
627
public AsynchronousThread(Socket socket) throws IOException
628
{this.virtualSocket = socket;}
633
// connect to SinglePortVirtualServerSocket
634
String hostName = virtualSocket.getInetAddress().getHostName();
635
int port = virtualSocket.getPort();
636
Socket v3 = new VirtualSocket(hostName, port);
638
// send an object to the client
639
ObjectOutputStream oos = new ObjectOutputStream(v3.getOutputStream());
640
oos.writeObject(new Integer(7));
645
catch (Exception e) {}
649
public static void main(String[] args)
651
new PrimeScenarioExampleServer().runPrimeScenario();
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
657
public void runN_SocketScenario()
661
// Create a SinglePortVirtualServerSocket and
662
// connect it to the server.
663
SinglePortVirtualServerSocket serverSocket
664
= new SinglePortVirtualServerSocket(5555);
665
InetSocketAddress connectAddress
666
= new InetSocketAddress(“localhost”, 6666);
667
serverSocket.setSoTimeout(10000);
668
serverSocket.connect(connectAddress);
670
// Accept connection requests for 3 virtual sockets.
671
Socket socket1 = serverSocket.accept();
672
Socket socket2 = serverSocket.accept();
673
Socket socket3 = serverSocket.accept();
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();
685
System.out.println(is1.read());
686
System.out.println(is2.read());
687
System.out.println(is3.read());
692
serverSocket.close();
694
catch (Exception e) {}
697
public static void main(String[] args)
699
new N_SocketScenarioClient().runN_SocketScenario();
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
705
public void runN_SocketScenario()
709
// Create and bind a MultiPortVirtualServerSocket.
710
MultiPortVirtualServerSocket serverSocket
711
= new MultiPortVirtualServerSocket(6666);
713
// Accept connection request from
714
// SinglePortVirtualServerSocket.
715
serverSocket.setSoTimeout(10000);
716
serverSocket.acceptServerSocketConnection();
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);
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());
737
serverSocket.close();
739
catch (Exception e) {}
742
public static void main(String[] args)
744
new N_SocketScenarioServer().runN_SocketScenario();
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
750
public void runSymmetricScenario()
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();
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);
764
serverSocket.setSoTimeout(10000);
765
serverSocket.connect(address);
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.
773
int port = serverSocket.getRemotePort();
774
Socket virtualSocket1 = new VirtualSocket("localhost", port);
775
InputStream is1 = virtualSocket1.getInputStream();
776
OutputStream os1 = virtualSocket1.getOutputStream();
778
// Create a virtual socket with SinglePortVirtualServerSocket.accept().
779
Socket virtualSocket2 = serverSocket.accept();
780
InputStream is2 = virtualSocket2.getInputStream();
781
OutputStream os2 = virtualSocket2.getOutputStream();
783
// Do some i/o and close sockets.
785
System.out.println(is1.read());
787
System.out.println(is2.read());
788
virtualSocket1.close();
789
virtualSocket2.close();
791
serverSocket.close();
793
catch (Exception e) {}
796
public static void main(String[] args)
798
new SymmetricScenarioClient().runSymmetricScenario();
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
804
public void runSymmetricScenario()
807
// Create ServerSocket and get synchronizing socket.
808
ServerSocket ss = new ServerSocket(6666);
809
Socket syncSocket = ss.accept();
811
InputStream is_sync = syncSocket.getInputStream();
812
OutputStream os_sync = syncSocket.getOutputStream();
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);
819
mpvss.setSoTimeout(10000);
820
int port = mpvss.acceptServerSocketConnection();
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.
828
SinglePortVirtualServerSocket spvss = new SinglePortVirtualServerSocket(port);
829
InetSocketAddress address = new InetSocketAddress("localhost", 5555);
830
spvss.setSoTimeout(5000);
831
spvss.connect(address);
833
// Indicate that the local SinglePortVirtualServerSocket is running.
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();
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();
848
// Do some i/o and close sockets.
849
os1.write(is1.read());
850
os2.write(is2.read());
851
virtualSocket1.close();
852
virtualSocket2.close();
856
catch (Exception e) {}
859
public static void main(String[] args)
861
new SymmetricScenarioServer().runSymmetricScenario();
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
867
public void runFactoryExample()
869
ServerSocketFactory ssf = VirtualServerSocketFactory.getDefault();
870
((VirtualServerSocketFactory) ssf).setOnServer();
871
SocketFactory sf = VirtualSocketFactory.getDefault();
872
useFactories(ssf, sf);
876
public void useFactories(ServerSocketFactory ssf, SocketFactory sf)
880
ServerSocket ss = ssf.createServerSocket(5555);
881
Socket s = sf.createSocket("localhost", 6666);
890
public static void main(String[] args)
892
new FactoryExample().runFactoryExample();
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'