At 11:52 03/12/2004 +0100, thierry wrote:

Hi,

LJ> Hello... the following script seems to work.

LJ> Factors to consider:
LJ> 1)The stack should be set to purge itself from memory upon closing
LJ> 2)Some firewalls might prevent the program from accepting
LJ> connections on a port
LJ> 3)This prevents multiple instances, but still does not quite allow
LJ> the two instances to communicate. Writing to a socket from one instance
LJ> seems to steal the ability of the other instance to listen to that
LJ> socket - I am still trying to work out how to do that.

humm, with my little experience, you probably need to differenciate the 1st
instance from the second. if the first do a accept connection ( Server mode )
the second instance should do a connect as a client. So, if you see yourself
in the netstat result then run a open socket on the port.

That's right. Since we're using sockets anyway, there's no need to use netstat at all.


Executive Summary :
the first instance goes into server mode, and accepts connections from subsequent instances


Technical Summary:
when an instance starts up, it attempts to open a connection to the chosen port.
If it succeeds, then there is already an instance running - and we have a connection to it.
If it fails, then there is no instance running - become the "server" and accept connections from others.


Exercise (left to the reader):
if the initial instance (server) is closed down, the client(s) should react to the "socket closed" event, such that one of them becomes a server, and the other clients re-connect to it.


Here's some code to do the initial problem - it has a bunch of error checking you could take it if you really wanted to, so it doesn't need to be quite this long. Note - I did this as a handler called "startUp" rather than in OpenStack or preOpenStack because I pulled most of this code out of an existing app and this was easier.

local lConns

on startUp
  if the openSockets <> empty then
    resetAll
    put "reset" into field "My Status"
    wait for 100 millisecs
  end if
  -- See if there is already an instance running
  open socket to "127.0.0.1:7654" with message "setMode"
end startUp

on setMode pMode
if pMode = "Server" then
-- we should be in server mode
put pMode into field "My Status"
accept connections on port "7654" with message "connectionMade"
else
-- another instance is running as server - need to be a client
put "Client" into field "My Status"
-- send a message to confirm
write "this is my input line" & cr to socket "127.0.0.1:7654"
read from socket "127.0.0.1:7654" until CR with message "receivedResponse"
end if
end setMode


-- Because this object does the Accepts and Opens, it gets close and error notifications
on socketClosed s
put lineOffset(s, lConns) into NConn
if NConn = 0 then
logWrite "Attempt to close a socket that is not open."
else
logWrite "Socket" && s && "closed."
delete line NConn of lConns
put lConns into field "Connections"
end if
end socketClosed


on socketError pSocket, pError
  if offset("10061", pError) > 0 then
    -- Connection refused - no-one is listening on this port already
    setMode "Server"
  else
    logWrite "Error :" && param(1) && param(2)
  end if
end socketError

-- client functions
on receivedResponse
  logWrite "Received response : " & param(2)
end receivedResponse

-- Server mode handlers
on connectionMade pOtherOne
  if char 1 to 9 of pOtherOne <> "127.0.0.1" then
    logWrite "Connection attempt from another machine - reject"
    close socket theOtherOne
    exit connectionMade
  end if
  if the number of lines in lConns >= 4 then
    logWrite "Too many connections - rejected."
    close socket theOtherOne
    exit connectionMade
  end if
  put pOtherOne & cr after lConns
  read from socket pOtherOne until CR with message "readsome"
end connectionMade


on readsome fromSocket, theInput put lineOffset(fromSocket, lConns) into NConn if NConn = 0 then logWrite "Input rejected - unknown Connection" & fromSocket read from socket fromSocket until CR with message "readsome" exit readsome end if -- echo it write "echo " & theInput & cr to socket fromSocket logWrite fromSocket & theInput read from socket fromSocket until CR with message "readsome" end readsome

on logWrite m
    put m & cr after field "Connections"
end logWrite

This works fine for me (Win2000), running one instance in the Player and the other within Rev itself. (And also running an echo server or clients written in other languages).


Note that it *should* be even easier than this - it makes no sense to have two applications listening on the same port; in Python or C you get an error (EADDRINUSE) return from the bind call (approx equivalent of Rev's "Accept") when another instance has already done an Accept on the port. Unfortunately, Rev doesn't seem to send an error in this case. I will play with this a bit more to make sure that I haven't done anything stupid, and then Bugzilla it.

-- Alex.
_______________________________________________
use-revolution mailing list
[EMAIL PROTECTED]
http://lists.runrev.com/mailman/listinfo/use-revolution

Reply via email to