97 lines
2.7 KiB
Rexx
Executable File
97 lines
2.7 KiB
Rexx
Executable File
#!/usr/bin/env rex
|
|
/*----------------------------------------------------------------------------*/
|
|
/* Simple socket server using socket function package */
|
|
|
|
srv = .myserver~new()
|
|
srv~listen()
|
|
|
|
exit
|
|
/* Rexx */
|
|
|
|
::class myserver
|
|
|
|
::method init
|
|
expose socket shutdown
|
|
socket = socksocket('AF_INET', 'SOCK_STREAM', '0')
|
|
shutdown = .false
|
|
|
|
::method monitor unguarded
|
|
expose socket shutdown
|
|
|
|
/* this seems to be the only cross platform way of cleanly shutting down.
|
|
this may not be the best method of shutting down, but does work on both
|
|
Linux and Windows */
|
|
say 'Press [Enter] To Shutdown'
|
|
pull seconds
|
|
if seconds~dataType("n") then do
|
|
say "shutdown in" seconds "sec"
|
|
call SysSleep seconds
|
|
end
|
|
|
|
shutdown = .true
|
|
|
|
/* create a socket (to connect to ourselves) */
|
|
socket = socksocket('AF_INET', 'SOCK_STREAM', 'IPPROTO_TCP')
|
|
|
|
/* specify the host we will connect to */
|
|
host.!family = 'AF_INET'
|
|
host.!addr = '127.0.0.1'
|
|
host.!port = '50010'
|
|
|
|
/* connect to the server (if it hasn't already shutdown) */
|
|
if sockconnect(socket, 'host.!') < 0 then
|
|
/* close the socket connection */
|
|
call sockclose socket
|
|
|
|
|
|
::method listen
|
|
expose socket shutdown
|
|
|
|
/* specify the host we will run as */
|
|
host.!family = 'AF_INET' -- Protocol family (only AF_INET is supported)
|
|
host.!addr = '127.0.0.1' -- localhost IP address
|
|
host.!port = '50010' -- Port number
|
|
|
|
/* bind to the host information */
|
|
call SockSetSockOpt socket, 'SOL_SOCKET', 'SO_REUSEADDR', 1
|
|
if sockbind(socket, 'host.!') < 0 then do
|
|
say 'SockBind failed:' errno
|
|
exit
|
|
end
|
|
|
|
/* start listening for new connections */
|
|
if socklisten(socket, 256) < 0 then do
|
|
say 'SockListen failed:' errno
|
|
exit
|
|
end
|
|
|
|
say "Server listening at" host.!addr':'host.!port
|
|
self~start('monitor') -- this will allow the server to be shutdown cleanly
|
|
|
|
do forever
|
|
cs = sockaccept(socket) -- prepare to accept a new client
|
|
if cs = -1 | shutdown then leave -- if the socket is closed (by monitor) sockaccept will fail
|
|
/* this will spawn a thread to handle the new client and then return to accept the next client */
|
|
self~start('respond', cs)
|
|
end
|
|
|
|
if cs <> -1 then
|
|
if sockclose(cs) < 0 then
|
|
say 'SockClose failed:' errno
|
|
|
|
if sockclose(socket) < 0 then
|
|
say 'SockClose failed:' errno
|
|
|
|
::method respond unguarded
|
|
use arg socket
|
|
|
|
do forever
|
|
/* get data from the client */
|
|
if sockrecv(socket, 'data', 1024) < 1 then leave
|
|
/* echo that data back to the client */
|
|
say data
|
|
call socksend socket, 'Echo:' data
|
|
end
|
|
|
|
::requires 'rxsock' LIBRARY
|