indexing description: "[ Sample ECHO server. This is an ECHO server that just sends everything back it has received. It listens with TCP and UDP. ]" date: "$Date$" revision: "$Revision$" class ECHO_SERVER inherit EM_SHARED_SUBSYSTEMS export {NONE} all end EM_SHARED_ERROR_HANDLER export {NONE} all end EM_TIME_SINGLETON export {NONE} all end KL_SHARED_ARGUMENTS export {NONE} all end create make feature {NONE} -- Initialization make is -- Run echo server. local a_port: INTEGER do Network_subsystem.enable if Arguments.argument_count = 0 then io.put_string ("Usage: echo_server %N") end -- Get port from first argument if Arguments.argument_count > 0 and Arguments.argument (1).is_integer then a_port := Arguments.argument (1).to_integer else a_port := 6666 end -- Get server up time from second argument if Arguments.argument_count > 1 and Arguments.argument (2).is_integer then server_up_time := Arguments.argument (2).to_integer * 1000 else server_up_time := 15000 end if server_up_time <= 0 then io.put_string ("Listening on port "+a_port.out+" (end with Ctrl-C)%N") else io.put_string ("Listening on port "+a_port.out+" for "+(server_up_time//1000).out+" seconds%N") end io.put_string ("Opening TCP server%N") create tcp_server.make tcp_server.set_port (a_port) tcp_server.connection_accepted_event.subscribe (agent handle_new_connection (?)) tcp_server.open io.put_string ("Opening UDP server%N") create udp_server.make udp_server.set_port (a_port) udp_server.data_received_event.subscribe (agent handle_udp_data_received (?)) udp_server.open -- Create and start polling event loop create event_loop.make_poll if server_up_time > 0 then event_loop.update_event.subscribe (agent handle_update_event) end event_loop.dispatch io.put_string ("Closing TCP server%N") tcp_server.close io.put_string ("Closing UDP server%N") udp_server.close Network_subsystem.disable rescue if Error_handler.last_error_code = Error_handler.Em_error_udp_open then io.put_string ("Error: UDP port alredy in use%N") elseif Error_handler.last_error_code = Error_handler.Em_error_tcp_open then io.put_string ("Error: TCP port alredy in use%N") end -- 'die' so no stack trace is shown Error_handler.die (1) end feature -- Access event_loop: EM_EVENT_LOOP -- Event loop server_up_time: INTEGER -- Time duration before server is closed next_connection_id: INTEGER -- An id for connections udp_server: EM_UDP_SOCKET -- UDP socket tcp_server: EM_TCP_SERVER_SOCKET -- TCP server socket feature -- Event management handle_new_connection (a_client: EM_TCP_CLIENT_SOCKET) is -- Handle new connection of `a_client'. do next_connection_id := next_connection_id + 1 io.put_string ("TCP: new connection from "+a_client.address.host_ip_port_as_string+" (client "+next_connection_id.out+")%N") -- The connection id and the client is saved as closed argument in the agent -- Normally you will have a list of your clients, but in this simple example this is not necessary a_client.connection_closed_event.subscribe (agent handle_closed_connection (a_client, next_connection_id)) a_client.data_received_event.subscribe (agent handle_tcp_data_received_event (a_client, next_connection_id, ?)) end handle_closed_connection (a_client: EM_TCP_CLIENT_SOCKET; a_connection_id: INTEGER) is -- Handle connection closed of `a_client'. do io.put_string ("TCP: connection closed from "+a_client.address.host_ip_port_as_string+" (client "+a_connection_id.out+")%N") end handle_tcp_data_received_event (a_client: EM_TCP_CLIENT_SOCKET; a_connection_id: INTEGER; data: STRING) is -- Handle data received of `a_client'. do io.put_string ("TCP: data received ("+data.count.out+" bytes) from "+a_client.address.host_ip_port_as_string+" (client "+a_connection_id.out+")%N") -- Just return the received data a_client.send_string (data) end handle_udp_data_received (a_packet: EM_UDP_PACKET) is -- Handle udp packet received event. do io.put_string ("UDP: packet received ("+a_packet.count.out+" bytes) from "+a_packet.address.host_ip_port_as_string+"%N") -- Just return the received packet. The address in the packet is -- the sender-address and thus will be returned to the sender udp_server.send (a_packet) end handle_update_event is -- Handle outside event. -- If time is up quit event loop. do if time.ticks > server_up_time then io.put_string ("Time is up%N") event_loop.stop end end end