mirror of
https://github.com/EiffelSoftware/eiffel-org.git
synced 2025-12-06 14:52:03 +01:00
Author:halw
Date:2008-12-04T21:55:33.000000Z git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@117 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
@@ -5,12 +5,19 @@
|
||||
==Graphical environment==
|
||||
|
||||
===What's new===
|
||||
* Innovative testing tools let you automatically test your software, extract test cases from failed execution as well as manually creating your own test cases.
|
||||
* Added ability to automatically license your Eiffel classes each time you save a class.
|
||||
* Added the '''argument_parser''' library which provides an easy way to manipulate command line arguments.
|
||||
* Added a new version of the EiffelNet library with IPv6 support. Because it has some breaking changes, the library is called '''net_ipv6''' and can be, in most cases, be used in place of the original EiffelNet library.
|
||||
|
||||
===Improvements===
|
||||
* Improved the library choice dialog which can also be customized to include your own locations.
|
||||
* Added support for <eiffel>note</eiffel> keyword and the updated <eiffel>variant</eiffel> keyword location in a loop through the environment.
|
||||
|
||||
===Changes===
|
||||
|
||||
===Bug fixes===
|
||||
* Code completion works even if the <eiffel>is</eiffel> is missing.
|
||||
|
||||
==Compiler==
|
||||
* Click [[Major changes between ISE Eiffel 6.2 and ISE Eiffel 6.3|here]] for the compiler release notes.
|
||||
@@ -26,6 +33,7 @@
|
||||
===EiffelBase===
|
||||
|
||||
===EiffelNet===
|
||||
* EiffelNet can select on 256 ports at the same time
|
||||
|
||||
===EiffelTime===
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
In the preceding examples each participant in a communication had to get ready to send or receive at specific stages of its life. Although this did not preclude asynchronous communication, it is sometimes desirable to make the scheme even more asynchronous, and control more decentralized, by letting each system simply specify certain communication events that it wants to monitor, and certain commands to be executed on occurrence of the specified events.
|
||||
|
||||
The commands are objects, instances of a general-purpose class <code>COMMAND </code>or its proper descendants. Class <code>COMMAND </code>has, among its features, a procedure ''execute'' which executes the current command; some commands are undoable and have an ''undo'' procedure.
|
||||
The commands are objects, instances of a general-purpose class <code>COMMAND</code> or its proper descendants. Class <code>COMMAND</code> has, among its features, a procedure <eiffel>execute</eiffel> which executes the current command; some commands are undoable and have an <eiffel>undo</eiffel> procedure.
|
||||
|
||||
In EiffelNet the possible events associated with a socket will be of three kind: a read event; a write event; or a special event (out of bounds operation). The command classes will be descendants of [[ref:/libraries/net/reference/poll_command_chart|POLL_COMMAND]] , an heir of <code>COMMAND</code>.
|
||||
|
||||
@@ -35,7 +35,7 @@ Here is the reader command for clients:
|
||||
|
||||
active_medium: NETWORK_DATAGRAM_SOCKET
|
||||
|
||||
execute is
|
||||
execute
|
||||
-- Obtain a packet of ten characters and print them.
|
||||
local
|
||||
rec_pack: DATAGRAM_PACKET
|
||||
@@ -49,7 +49,8 @@ Here is the reader command for clients:
|
||||
until
|
||||
i > 9
|
||||
loop
|
||||
io.putchar (rec_pack.element (i)); i := i + 1
|
||||
io.putchar (rec_pack.element (i))
|
||||
i := i + 1
|
||||
end
|
||||
io.new_line
|
||||
end
|
||||
@@ -58,7 +59,7 @@ Here is the reader command for clients:
|
||||
|
||||
</code>
|
||||
|
||||
The ''execute'' 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>
|
||||
class
|
||||
CLIENT_DATAGRAM_WRITER
|
||||
@@ -79,7 +80,7 @@ The ''execute'' procedure reads a packet of ten characters and prints these char
|
||||
|
||||
active_medium: NETWORK_DATAGRAM_SOCKET
|
||||
|
||||
execute is
|
||||
execute
|
||||
-- Make a packet with characters 'a' to 'k' in successive positions.
|
||||
local
|
||||
sen_pack: DATAGRAM_PACKET
|
||||
@@ -105,7 +106,7 @@ The ''execute'' procedure reads a packet of ten characters and prints these char
|
||||
|
||||
Once the commands have been defined, it suffices for the server and the client to associate instances of these commands with the appropriate.
|
||||
|
||||
The abstraction needed for this purpose is provided by class <code>MEDIUM_POLLER</code>. An instance of this class knows about a number of commands, each associated with a certain socket in read, write or special event mode. By applying procedure ''execute'' to such a medium poller, you direct it to monitor these sockets for the corresponding events and to execute the command associated with each event that will be received. Procedure ''execute'' takes two integer arguments: the maximum number of sockets to monitor, and the timeout in milliseconds.
|
||||
The abstraction needed for this purpose is provided by class <code>MEDIUM_POLLER</code>. An instance of this class knows about a number of commands, each associated with a certain socket in read, write or special event mode. By applying procedure <eiffel>execute</eiffel> to such a medium poller, you direct it to monitor these sockets for the corresponding events and to execute the command associated with each event that will be received. Procedure <eiffel>execute</eiffel> takes two integer arguments: the maximum number of sockets to monitor, and the timeout in milliseconds.
|
||||
|
||||
Here is the server built with this mechanism:
|
||||
<code>
|
||||
@@ -118,7 +119,7 @@ Here is the server built with this mechanism:
|
||||
|
||||
feature
|
||||
|
||||
make is
|
||||
make
|
||||
-- Create read and write commands, attach them to a poller,
|
||||
-- set up the poller for execution.
|
||||
local
|
||||
@@ -140,14 +141,13 @@ Here is the server built with this mechanism:
|
||||
</code>
|
||||
|
||||
|
||||
Procedure ''make'' 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 ''execute'' 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 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.
|
||||
|
||||
The procedures ''make_read_only'' and ''make_write_only'' 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 '''create''' ''poller''l. ''make_read_only''. For clarity, however, the above class and the next separate calls to these procedures from the creation of the poller, which uses ''make'' as creation procedure.
|
||||
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 '''create''' ''poller''l. <eiffel>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:
|
||||
<code>
|
||||
class
|
||||
|
||||
POLLING_CLIENT
|
||||
|
||||
creation
|
||||
@@ -155,7 +155,7 @@ creation
|
||||
|
||||
feature
|
||||
|
||||
make is
|
||||
make
|
||||
-- Create read and write commands, attach them to a poller,
|
||||
-- set up the poller for execution.
|
||||
local
|
||||
@@ -187,11 +187,11 @@ end
|
||||
|
||||
===9.4 A less deterministic scheme===
|
||||
|
||||
Although the example uses the event-driven mechanisms of EiffelNet, it is still relatively deterministic in that it follows a precise protocol defined by a strict sequence of read and write operations on both sides. This is why every call to ''execute'' is preceded by a call to either ''make_read_only'' or ''make_write_only ''to set up the poller in the appropriate mode.
|
||||
Although the example uses the event-driven mechanisms of EiffelNet, it is still relatively deterministic in that it follows a precise protocol defined by a strict sequence of read and write operations on both sides. This is why every call to <eiffel>execute</eiffel> is preceded by a call to either <eiffel>make_read_only</eiffel> or <eiffel>make_write_only</eiffel> to set up the poller in the appropriate mode.
|
||||
|
||||
A less deterministic scheme may often be desirable, where you simply enter a number of commands (read, write, out of bounds processing) into a poller and then wait for arbitrary events to occur and trigger commands. There is no need with this scheme to know in advance the order in which events may occur: a read event will trigger the command entered into the poller through ''put_read_command''; a write event will trigger the command entered through ''put_write_command''.
|
||||
A less deterministic scheme may often be desirable, where you simply enter a number of commands (read, write, out of bounds processing) into a poller and then wait for arbitrary events to occur and trigger commands. There is no need with this scheme to know in advance the order in which events may occur: a read event will trigger the command entered into the poller through <eiffel>put_read_command</eiffel>; a write event will trigger the command entered through <eiffel>put_write_command</eiffel>.
|
||||
|
||||
To achieve this behavior, simply create the poller using ''make'' as creation procedure. This will set up the poller so as to accept all socket events, and enter into event-driven command execution by calling ''execute'' on the poller.
|
||||
To achieve this behavior, simply create the poller using <eiffel>make</eiffel> as creation procedure. This will set up the poller so as to accept all socket events, and enter into event-driven command execution by calling <eiffel>execute</eiffel> on the poller.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
The last example exercises most of EiffelNet's major facilities. It consists of a server that allows an arbitrary number of clients to connect to it. Each time the user of one of the client systems types a line on the keyboard, the client sends this character to the server, which then broadcasts it to all the clients (including the original sender). This scheme allows several people to talk together, hence the names chosen: the server class is called <code>CHAT</code>, and the client is called <code>JOIN</code>.
|
||||
|
||||
The example uses the network mode of communication, based on the [[ref:libraries/net/reference/network_client_chart|NETWORK_CLIENT]] and [[ref:libraries/net/reference/network_server_chart|NETWORK_SERVER ]] classes. It uses automatic polling through [[ref:libraries/net/reference/medium_poller_chart|MEDIUM_POLLER]] as in the previous example; the relevant command is given by class <code> CONNECTION </code>, an heir of [[ref:libraries/net/reference/poll_command_chart|POLL_COMMAND]] . The information exchanged between the server and its clients is described by class <code> MESSAGE </code>, an heir of [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] [ [[ref:libraries/base/reference/string_8_chart|STRING]] ] similar to the earlier examples' OUR_MESSAGE (see [[Working at predefined level|see "Object structures"]] ). Attributes include, the name ''client_name'' of the client that has sent this message, the boolean ''new'' indicating whether the current message is the first from a client that is trying to connect to the server, and ''over ''indicating that the message is the last sent by a client before disconnecting.
|
||||
The example uses the network mode of communication, based on the [[ref:libraries/net/reference/network_client_chart|NETWORK_CLIENT]] and [[ref:libraries/net/reference/network_server_chart|NETWORK_SERVER ]] classes. It uses automatic polling through [[ref:libraries/net/reference/medium_poller_chart|MEDIUM_POLLER]] as in the previous example; the relevant command is given by class <code>CONNECTION</code>, an heir of [[ref:libraries/net/reference/poll_command_chart|POLL_COMMAND]] . The information exchanged between the server and its clients is described by class <code>MESSAGE</code>, an heir of [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] [ [[ref:libraries/base/reference/string_8_chart|STRING]] ] similar to the earlier examples' OUR_MESSAGE (see [[Working at predefined level]] ). Attributes include, the name <eiffel>client_name</eiffel> of the client that has sent this message, the boolean <eiffel>new</eiffel> indicating whether the current message is the first from a client that is trying to connect to the server, and <eiffel>over</eiffel> indicating that the message is the last sent by a client before disconnecting.
|
||||
|
||||
The server maintains a list of the currently active connections. In the ''receive'' routine, it checks on the main socket for any client trying to connect. The socket is set to be non-blocking to enable the server to continue checking the already connected clients. If the connection is successful, the server sends to the new client the list of clients already connected and adds the new connection to its list. Then it polls the connections in the list, and processes the messages, if any. If the message is tagged ''new'', the server sends a message to all the clients indicating that a new client has joined the server; if it is tagged ''over'', it sends a message indicating that the client has opted out.
|
||||
The server maintains a list of the currently active connections. In the <eiffel>receive</eiffel> routine, it checks on the main socket for any client trying to connect. The socket is set to be non-blocking to enable the server to continue checking the already connected clients. If the connection is successful, the server sends to the new client the list of clients already connected and adds the new connection to its list. Then it polls the connections in the list, and processes the messages, if any. If the message is tagged <eiffel>new</eiffel>, the server sends a message to all the clients indicating that a new client has joined the server; if it is tagged <eiffel>over</eiffel>, it sends a message indicating that the client has opted out.
|
||||
|
||||
Each client uses the [[ref:libraries/net/reference/medium_poller_chart|MEDIUM_POLLER]] to check any message coming from the server and immediately displays any such message. It also checks a special connection, created with ''io''l''input'' as a medium, to check what the user is typing and then send it to the server. If the user types ''bye'', the client terminates, sending a message tagged ''over ''to the server.
|
||||
Each client uses the [[ref:libraries/net/reference/medium_poller_chart|MEDIUM_POLLER]] to check any message coming from the server and immediately displays any such message. It also checks a special connection, created with <eiffel>io.input</eiffel> as a medium, to check what the user is typing and then send it to the server. If the user types ''bye'', the client terminates, sending a message tagged <eiffel>over</eiffel> to the server.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -42,17 +42,17 @@ Whenever the server needs to exchange objects with one of the clients, it obtain
|
||||
soc2.close
|
||||
</code>
|
||||
|
||||
Procedure ''accept ''ensures synchronization with the client. When communication is established, ''accept'' creates a new socket which will be accessible through attribute ''accepted'', whose value is here assigned to the local entity ''soc2''. To receive objects, the server will use operations of the form introduced earlier ( [[An overview of EiffelNet Mechanisms|An overview of EiffelNet, sending and receiving object structures]] ):
|
||||
Procedure <eiffel>accept</eiffel> ensures synchronization with the client. When communication is established, <eiffel>accept</eiffel> creates a new socket which will be accessible through attribute <eiffel>accepted</eiffel>, whose value is here assigned to the local entity <eiffel>soc2</eiffel>. To receive objects, the server will use operations of the form introduced earlier ( [[An overview of EiffelNet Mechanisms|An overview of EiffelNet, sending and receiving object structures]] ):
|
||||
<code>
|
||||
struct ?= soc2.retrieved</code>
|
||||
|
||||
applying to ''soc2'', not ''soc1''; this makes ''soc1 ''available to accept connections with other clients, a fundamental feature of client-server mechanisms.
|
||||
applying to <eiffel>soc2</eiffel>, not <eiffel>soc1</eiffel>; this makes <eiffel>soc1</eiffel> available to accept connections with other clients, a fundamental feature of client-server mechanisms.
|
||||
|
||||
The operation ''soc2''. ''close'' which terminates the above sequence closes the new socket. In principle this is not necessary, since garbage collection should eventually reclaim the socket object, and the ''dispose'' procedure of the corresponding socket class includes a call to ''close''. But the risk exists that you run out of sockets before garbage collection reclaims all currently opened sockets, so it is preferable to include the ''close'' calls explicitly.
|
||||
The operation <eiffel>soc2</eiffel>. <eiffel>close</eiffel> which terminates the above sequence closes the new socket. In principle this is not necessary, since garbage collection should eventually reclaim the socket object, and the <eiffel>dispose</eiffel> procedure of the corresponding socket class includes a call to <eiffel>close</eiffel>. But the risk exists that you run out of sockets before garbage collection reclaims all currently opened sockets, so it is preferable to include the <eiffel>close</eiffel> calls explicitly.
|
||||
|
||||
At the end of the processing it is necessary to close the original socket ''soc1'' but also to unlink it. The feature ''cleanup'' from class ''SOCKET'' takes care of both closing and unlinking.
|
||||
At the end of the processing it is necessary to close the original socket <eiffel>soc1</eiffel> but also to unlink it. The feature <eiffel>cleanup</eiffel> from class <eiffel>SOCKET</eiffel> takes care of both closing and unlinking.
|
||||
|
||||
Here is the server class based on these principles. The actual processing has been put aside in a procedure ''process''.
|
||||
Here is the server class based on these principles. The actual processing has been put aside in a procedure <eiffel>process</eiffel>.
|
||||
<code>
|
||||
class
|
||||
OUR_SERVER
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
[[Property:uuid|ba27b7dd-77db-7f6f-9b8c-2a3111d9d432]]
|
||||
{{note|The example classes discussed in this section appear in the subdirectory ''datagram'' of the example directory. }}
|
||||
|
||||
Using datagram sockets implies a few differences from the preceding schemes. You create a [[ref:libraries/net/reference/network_datagram_socket_chart|NETWORK_DATAGRAM_SOCKET]] or a <eiffel>UNIX_DATAGRAM_SOCKET</eiffel> as before. You do not need to call ''listen'', ''accept'' or ''connect''. Once you have created your sockets using the ''make_client ''or ''make_server'' creation procedure, you can use the ''send ''and ''received ''routines, specifying the socket to which you want to send, or from which you want to receive.
|
||||
Using datagram sockets implies a few differences from the preceding schemes. You create a [[ref:libraries/net/reference/network_datagram_socket_chart|NETWORK_DATAGRAM_SOCKET]] or a <eiffel>UNIX_DATAGRAM_SOCKET</eiffel> as before. You do not need to call <eiffel>listen</eiffel>, <eiffel>accept</eiffel> or <eiffel>connect</eiffel>. Once you have created your sockets using the <eiffel>make_client</eiffel> or <eiffel>make_server</eiffel> creation procedure, you can use the <eiffel>send</eiffel> and <eiffel>received</eiffel> routines, specifying the socket to which you want to send, or from which you want to receive.
|
||||
|
||||
The command ''send ''takes an argument of type [[ref:libraries/net/reference/datagram_packet_chart|DATAGRAM_PACKET]] , and the query ''received ''returns a result of this type. [[ref:libraries/net/reference/datagram_packet_chart|DATAGRAM_PACKET]] is an heir of class [[ref:libraries/net/reference/packet_chart|PACKET]] , itself an heir of [[ref:libraries/base/reference/array_chart|ARRAY]] [ [[ref:libraries/base/reference/character_8_chart|CHARACTER]] ]. Class [[ref:libraries/net/reference/datagram_packet_chart|DATAGRAM_PACKET]] makes it possible, through the query ''number'' and the associated command ''set_number'', to associate a packet number with each packet. This compensates for lack of guaranteed sequencing of datagram sockets: the sender can number packets through ''set_number'', and the receiver can check that all packets have been received through ''number'', asking the sender to re-emit missing objects.
|
||||
The command <eiffel>send</eiffel> takes an argument of type [[ref:libraries/net/reference/datagram_packet_chart|DATAGRAM_PACKET]] , and the query <eiffel>received</eiffel> returns a result of this type. [[ref:libraries/net/reference/datagram_packet_chart|DATAGRAM_PACKET]] is an heir of class [[ref:libraries/net/reference/packet_chart|PACKET]] , itself an heir of [[ref:libraries/base/reference/array_chart|ARRAY]] [ [[ref:libraries/base/reference/character_8_chart|CHARACTER]] ]. Class [[ref:libraries/net/reference/datagram_packet_chart|DATAGRAM_PACKET]] makes it possible, through the query <eiffel>number</eiffel> and the associated command <eiffel>set_number</eiffel>, to associate a packet number with each packet. This compensates for lack of guaranteed sequencing of datagram sockets: the sender can number packets through <eiffel>set_number</eiffel>, and the receiver can check that all packets have been received through <eiffel>number</eiffel>, asking the sender to re-emit missing objects.
|
||||
|
||||
The text of this example is similar to what appears below (in a more general setting involving event-driven computation) for the next example.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user