1: #!/usr/bin/rexx
2: /*----------------------------------------------------------------------------*/
3: /* */
4: /* Description: Simple socket server using socket class */
5: /* */
6: /* Copyright (c) 2007-2008 Rexx Language Association. All rights reserved. */
7: /* */
8: /* This program and the accompanying materials are made available under */
9: /* the terms of the Common Public License v1.0 which accompanies this */
10: /* distribution. A copy is also available at the following address: */
11: /* http://www.ibm.com/developerworks/oss/CPLv1.0.htm */
12: /* */
13: /* Redistribution and use in source and binary forms, with or */
14: /* without modification, are permitted provided that the following */
15: /* conditions are met: */
16: /* */
17: /* Redistributions of source code must retain the above copyright */
18: /* notice, this list of conditions and the following disclaimer. */
19: /* Redistributions in binary form must reproduce the above copyright */
20: /* notice, this list of conditions and the following disclaimer in */
21: /* the documentation and/or other materials provided with the distribution. */
22: /* */
23: /* Neither the name of Rexx Language Association nor the names */
24: /* of its contributors may be used to endorse or promote products */
25: /* derived from this software without specific prior written permission. */
26: /* */
27: /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
28: /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
29: /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
30: /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
31: /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
32: /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
33: /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
34: /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
35: /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
36: /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
37: /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
38: /* */
39: /* Author: David Ruggles */
40: /* Adapted: Ruurd Idenburg - 2015/03/25 - host and port as arguments */
41: /* input echoed to STDOUT */
42: /* */
43: /*----------------------------------------------------------------------------*/
44: parse arg hostname port
45: if hostname=='' then hostname = 'localhost'
46: if port=='' then port = 726578
47:
48: srv = .myserver~new(hostname, port)
49: srv~listen()
50:
51: ::requires 'socket.cls'
52:
53: ::class myserver
54:
55: ::method init
56: expose sock hostname port shutdown
57: use strict arg hostname, port
58:
59: /* instaniate an instance of the socket class */
60: sock = .socket~new()
61:
62: shutdown = .false
63:
64: ::method monitor unguarded
65: expose sock hostname port shutdown
66:
67: /* this seems to be the only cross platform way of cleanly shutting down.
68: this may not be the best method of shutting down, but does work on both
69: Linux and Windows */
70: say 'Press [Enter] To Shutdown'
71: pull .
72:
73: shutdown = .true
74:
75: /* instaniate an instance of the socket class */
76: sock = .socket~new()
77:
78: host = .inetaddress~new(hostname, port)
79: /* connect to the server (if it hasn't already shutdown) */
80: if sock~connect(host) < 0 then
81: /* close the socket connection */
82: sock~close()
83:
84: ::method listen
85: expose sock hostname port shutdown
86: --trace i
87:
88: /* instaniate an instance of the inetaddress class
89: with the host information of the server we will
90: contact: localhost and port 726578
91: we use the "gethostid" class method of the socket
92: class to determine the localhost address */
93: host = .inetaddress~new(hostname, port)
94:
95: /* bind to the host information */
96: if sock~bind(host) < 0 then do
97: say 'Bind Failed'
98: exit
99: end
100:
101: if sock~listen(256) < 0 then do
102: say 'Listen Failed'
103: exit
104: end
105:
106: self~start('monitor') -- this will allow the server to be shutdown cleanly
107:
108: do forever
109: csock = sock~accept() -- prepare to accept a new client
110: if .nil = csock | shutdown then leave -- if the socket has closed or the shutdown flag is set
111: /* this will spawn a thread to handle the new client and then return to accept the next client */
112: self~start('respond', csock)
113: end
114: --trace ?i
115: if csock~isa(.socket) then
116: if csock~close() < 0 then
117: say 'SockClose Failed'
118:
119: if sock~close() < 0 then
120: say 'SockClose Failed'
121:
122: ::method respond unguarded
123: use arg sock
124: do forever
125: /* get data from the client */
126: data = sock~recv(1024)
127: if data = .nil | data = '' then leave
128: .output~lineout(data)
129: /* echo that data back to the client */
130: --sock~send('Echo:' data)
131: end