mirror of
https://github.com/EiffelSoftware/eiffel-org.git
synced 2025-12-08 07:42:33 +01:00
Updated code examples from the examples in the EiffelStudio distribution. Updated discussion to reflect changes in code.
Author:halw Date:2012-04-22T19:59:12.000000Z git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@1078 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
@@ -14,12 +14,12 @@ In EiffelNet the possible events associated with a socket will be of three kind:
|
|||||||
|
|
||||||
===9.2 Command classes===
|
===9.2 Command classes===
|
||||||
|
|
||||||
The example uses four command classes: <code>CLIENT_DATAGRAM_READER</code>, <code>CLIENT_DATAGRAM_WRITER</code> and their counterpart for servers, representing operations that must be triggered in the case of a read event and a write event.
|
The example uses three command classes: <code>DATAGRAM_READER</code>, used by both clients and servers, and specialized versions of a datagram writer for clients, <code>CLIENT_DATAGRAM_WRITER</code>, and servers, <code>SERVER_DATAGRAM_WRITER</code>. These classes model operations that must be triggered in the case of a read event and a write event.
|
||||||
|
|
||||||
Here is the reader command for clients:
|
Here is the common reader command:
|
||||||
<code>
|
<code>
|
||||||
class
|
class
|
||||||
CLIENT_DATAGRAM_READER
|
DATAGRAM_READER
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
@@ -29,39 +29,37 @@ inherit
|
|||||||
end
|
end
|
||||||
|
|
||||||
create
|
create
|
||||||
|
|
||||||
make
|
make
|
||||||
|
|
||||||
feature
|
feature
|
||||||
|
|
||||||
active_medium: NETWORK_DATAGRAM_SOCKET
|
active_medium: NETWORK_DATAGRAM_SOCKET
|
||||||
|
|
||||||
execute
|
execute (arg: ANY)
|
||||||
-- Obtain a packet of ten characters and print them.
|
|
||||||
local
|
local
|
||||||
rec_pack: DATAGRAM_PACKET
|
rec_pack: PACKET
|
||||||
|
datagram: DATAGRAM_PACKET
|
||||||
i: INTEGER
|
i: INTEGER
|
||||||
do
|
do
|
||||||
rec_pack := active_medium.received (10, 0)
|
rec_pack := active_medium.received (10, 0)
|
||||||
io.putint (rec_pack.packet_number)
|
create datagram.make_from_managed_pointer (rec_pack.data)
|
||||||
|
io.putint (datagram.packet_number)
|
||||||
io.new_line
|
io.new_line
|
||||||
from
|
from i := 0 until i > 9 loop
|
||||||
i := 0
|
io.putchar (datagram.element (i))
|
||||||
until
|
|
||||||
i > 9
|
|
||||||
loop
|
|
||||||
io.putchar (rec_pack.element (i))
|
|
||||||
i := i + 1
|
i := i + 1
|
||||||
end
|
end
|
||||||
io.new_line
|
io.new_line
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end -- class DATAGRAM_READER
|
||||||
|
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
The <eiffel>execute</eiffel> procedure reads a packet of ten characters and prints these characters. Its counterpart in the writing command will produce these ten packets:
|
The <eiffel>execute</eiffel> procedure reads a packet of ten characters and prints these characters. Its counterpart in the writing command will produce these ten packets:
|
||||||
<code>
|
<code>
|
||||||
class
|
class
|
||||||
CLIENT_DATAGRAM_WRITER
|
CLIENT_DATAGRAM_WRITER
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
@@ -71,35 +69,30 @@ inherit
|
|||||||
active_medium
|
active_medium
|
||||||
end
|
end
|
||||||
|
|
||||||
BASIC_ROUTINES
|
|
||||||
|
|
||||||
create
|
create
|
||||||
|
|
||||||
make
|
make
|
||||||
|
|
||||||
feature
|
feature
|
||||||
|
|
||||||
active_medium: NETWORK_DATAGRAM_SOCKET
|
active_medium: NETWORK_DATAGRAM_SOCKET
|
||||||
|
|
||||||
execute
|
execute (arg: ANY)
|
||||||
-- Make a packet with characters 'a' to 'k' in successive positions.
|
|
||||||
local
|
local
|
||||||
sen_pack: DATAGRAM_PACKET
|
sen_pack: DATAGRAM_PACKET
|
||||||
ccode: INTEGER
|
char: CHARACTER
|
||||||
do
|
do
|
||||||
|
-- Make packet with characters `a' to `j' in successive positions
|
||||||
create sen_pack.make (10)
|
create sen_pack.make (10)
|
||||||
from
|
from char := 'a' until char > 'j' loop
|
||||||
ccode := charcode ('a')
|
sen_pack.put_element (char, char |-| 'a')
|
||||||
until
|
char := char.next
|
||||||
ccode > charcode ('k')
|
|
||||||
loop
|
|
||||||
sen_pack.put_element (charconv (ccode), ccode -- charcode ('a'))
|
|
||||||
ccode := ccode + 1
|
|
||||||
end
|
end
|
||||||
sen_pack.set_packet_number (1)
|
sen_pack.set_packet_number (1)
|
||||||
active_medium.send (sen_pack, Void, 0)
|
active_medium.send (sen_pack, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end -- class CLIENT_DATAGRAM_WRITER
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
===9.3 The server and the client===
|
===9.3 The server and the client===
|
||||||
@@ -110,71 +103,84 @@ The abstraction needed for this purpose is provided by class <code>MEDIUM_POLLER
|
|||||||
|
|
||||||
Here is the server built with this mechanism:
|
Here is the server built with this mechanism:
|
||||||
<code>
|
<code>
|
||||||
class
|
class
|
||||||
|
|
||||||
POLLING_SERVER
|
POLLING_SERVER
|
||||||
|
|
||||||
create
|
create
|
||||||
|
|
||||||
make
|
make
|
||||||
|
|
||||||
feature
|
feature
|
||||||
|
|
||||||
make
|
make (argv: ARRAY [STRING])
|
||||||
-- Create read and write commands, attach them to a poller,
|
|
||||||
-- set up the poller for execution.
|
|
||||||
local
|
local
|
||||||
soc: NETWORK_DATAGRAM_SOCKET
|
soc: detachable NETWORK_DATAGRAM_SOCKET
|
||||||
poller: MEDIUM_POLLER
|
ps: MEDIUM_POLLER
|
||||||
readcomm: SERVER_DATAGRAM_READER
|
readcomm: DATAGRAM_READER
|
||||||
writecomm: SERVER_DATAGRAM_WRITER
|
writecomm: SERVER_DATAGRAM_WRITER
|
||||||
do
|
do
|
||||||
create soc.make_server_by_port (6530)
|
if argv.count /= 2 then
|
||||||
create poller.make
|
io.error.putstring ("Usage: ")
|
||||||
create readcomm.make (soc); poller.put_read_command (readcomm)
|
io.error.putstring (argv.item (0))
|
||||||
create writecomm.make (soc); poller.put_write_command (writecomm)
|
io.error.putstring (" portnumber%N")
|
||||||
poller.make_read_only; poller.execute (15, 20000)
|
else
|
||||||
poller.make_write_only; poller.execute (15, 20000)
|
create soc.make_bound (argv.item (1).to_integer)
|
||||||
soc.close
|
create ps.make_read_only
|
||||||
|
create readcomm.make (soc)
|
||||||
|
ps.put_read_command (readcomm)
|
||||||
|
create writecomm.make (soc)
|
||||||
|
ps.put_write_command (writecomm)
|
||||||
|
ps.execute (15, 20000)
|
||||||
|
ps.make_write_only
|
||||||
|
ps.execute (15, 20000)
|
||||||
|
soc.close
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
if soc /= Void and then not soc.is_closed then
|
||||||
|
soc.close
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end -- POLLING_SERVER
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
|
|
||||||
Procedure <eiffel>make</eiffel> creates three objects: a socket, which it associates with a specific port; a poller; and a read command (an instance of SERVER_DATAGRAM_READER), which it attaches to the socket. It then enters the read command into the poller, and does the same thing with a write command. It sets up the poller to accept read commands only and then executes the poller; this will enable the server to get the read event triggered by the client's write command (as it appears below in the text of class <code>POLLING_CLIENT</code>). Then the server reverses the poller's set-up to write-only, and calls <eiffel>execute</eiffel> again.
|
Procedure <eiffel>make</eiffel> creates three objects: a socket, which it associates with a specific port; a poller; and a read command (an instance of DATAGRAM_READER), which it attaches to the socket. It then enters the read command into the poller, and does the same thing with a write command. It sets up the poller to accept read commands only and then executes the poller; this will enable the server to get the read event triggered by the client's write command (as it appears below in the text of class <code>POLLING_CLIENT</code>). Then the server reverses the poller's set-up to write-only, and calls <eiffel>execute</eiffel> again.
|
||||||
|
|
||||||
The procedures <eiffel>make_read_only</eiffel> and <eiffel>make_write_only</eiffel> are creation procedures, so that it is possible in a single instruction to create a poller and set it up for read-only or write-only, as in <eiffel>create poller.make_read_only</eiffel>. For clarity, however, the above class and the next separate calls to these procedures from the creation of the poller, which uses <eiffel>make</eiffel> as creation procedure.
|
|
||||||
|
|
||||||
The client follows the same scheme, reversing the order of read and write operations:
|
The client follows the same scheme, reversing the order of read and write operations:
|
||||||
<code>
|
<code>
|
||||||
class
|
class
|
||||||
POLLING_CLIENT
|
POLLING_CLIENT
|
||||||
|
|
||||||
create
|
create
|
||||||
|
|
||||||
make
|
make
|
||||||
|
|
||||||
feature
|
feature
|
||||||
|
|
||||||
make
|
make (argv: ARRAY [STRING])
|
||||||
-- Create read and write commands, attach them to a poller,
|
|
||||||
-- set up the poller for execution.
|
|
||||||
local
|
local
|
||||||
soc: NETWORK_DATAGRAM_SOCKET
|
soc: detachable NETWORK_DATAGRAM_SOCKET
|
||||||
poller: MEDIUM_POLLER
|
ps: MEDIUM_POLLER
|
||||||
readcomm: DATAGRAM_READER
|
readcomm: DATAGRAM_READER
|
||||||
writecomm: DATAGRAM_WRITER
|
writecomm: CLIENT_DATAGRAM_WRITER
|
||||||
do
|
do
|
||||||
create soc.make_client_by_port (6530, "serverhost")
|
if argv.count /= 3 then
|
||||||
create poller.make
|
io.error.putstring ("Usage: ")
|
||||||
create readcomm.make (soc)
|
io.error.putstring (argv.item (0))
|
||||||
poller.put_read_command (readcomm)
|
io.error.putstring (" hostname portnumber%N")
|
||||||
create writecomm.make (soc)
|
else
|
||||||
poller.put_write_command (writecomm)
|
create soc.make_targeted (argv.item (1), argv.item (2).to_integer)
|
||||||
poller.make_write_only
|
create ps.make_write_only
|
||||||
poller.execute (15, 20000)
|
create readcomm.make (soc)
|
||||||
poller.make_read_only
|
ps.put_read_command (readcomm)
|
||||||
poller.execute (15, 20000)
|
create writecomm.make (soc)
|
||||||
soc.close
|
ps.put_write_command (writecomm)
|
||||||
|
ps.execute (15, 20000)
|
||||||
|
ps.make_read_only
|
||||||
|
ps.execute (15, 20000)
|
||||||
|
soc.close
|
||||||
|
end
|
||||||
rescue
|
rescue
|
||||||
if soc /= Void and then not soc.is_closed then
|
if soc /= Void and then not soc.is_closed then
|
||||||
soc.close
|
soc.close
|
||||||
|
|||||||
Reference in New Issue
Block a user