More Socket Problems.........

Alex Tweedly alex at tweedly.net
Thu Feb 28 17:37:39 EST 2008


Dave wrote:
> Opps!
>
> Just realized that the IP Addresses are wrong in the example, in the 
> real app it's ok. I forgot that my router munges the the LAN IP 
> Addresses, so where I've put 192.168.1.101, read 192.168.1.87 and 
> where 192.168.1.102 read 192.168.1.105.
>
> Another question is:
>
> Why do I get a read error and not a write error:
>
> socketError: 192.168.1.87:6000|looktowindward Error 54 reading socket
>
> I'm not reading on the Client, I'm trying to try data.
>
You don't get a read error. You get a socket error (-- Connection reset 
by peer. This occurs when an established connection is shut down for 
some reason by the remote computer.) which the error string misleadingly 
indicates was a read error. This probably comes from your system (which 
OS etc. are you using ?), and is merely passed along by Rev.

It probably does happen when you try to write to the socket after it has 
been closed.

I'd recommend adding a 'socketClosed' handler and see if that helps ...

>
> Questions:
>
> Why do I sometimes not get a socketError or a socketTimeout ?
>
> Why does it sometimes repeat (as it should) for a few times and then 
> stop?
>
Don't know :-(  but try adding the socketClosed handler and see if that 
helps. I have also asked some questions / made some suggestions below.
If it doesn't, resend this log
> Here is the code:
>
> The mouseUp handler are in the main stack of the app and the
>
>
> The following is including in the App using the "start using" command:
>
>
> --  StartServer
>
> function StartServer theServerPortNumber,theClientAllowList
>
>   get DebugLogString("StartServer - Accept:" && theServerPortNumber)
>
>   put theClientAllowList into sgServerClientAllowList
>   accept connections on theServerPortNumber with message 
> "ServerContactedByClient"
>
>   return empty
> end StartServer
>
>
> --  ServerContactedByClient
>
> on ServerContactedByClient theIPAddress
>   local myClientIPAddress
>   local myResult
>
>   put the result into myResult
>
what do you expect 'the result' to contain at this point ?
>   get DebugLogString("ServerContactedByClient:" && theIPAddress && 
> myResult)
>
>   if myResult <> empty then
>     breakpoint
>     exit ServerContactedByClient
>   end if
>
>   set the itemDelimiter to ":"
>   put item 1 of theIPAddress into myClientIPAddress
>
>   if myClientIPAddress is not among the lines of 
> sgServerClientAllowList then
>     get DebugLogString("ServerContactedByClient, Bad Client:" && 
> theIPAddress)
>     close socket theIPAddress
I'd recommend a 'exit ServerContactedByClient" at this point - otherwise 
you are about to read from a socket you just closed.
>   end if
>
>   read from socket theIPAddress for kPacketCountSize chars with 
> message "ServerReceivedPacketSize"
>
> end ServerContactedByClient
>
>
>
> --  ServerReceivedPacketSize
>
> on ServerReceivedPacketSize theIPAddress,thePacketSize
>   local myResult
>   local myPacketData
>   local myPacketID
>   local myPacketCommand
>   local myConnectionID
>
>   put the result into myResult
>
again, what do you expect in 'the result' here ?
>   get DebugLogString("ServerReceivedPacketSize:" && theIPAddress && 
> thePacketSize && myResult)
>
>   if myResult <> empty then
>     get DebugLogString("ServerReceivedPacketSize, Error:" && myResult)
>     breakpoint
>   end if
>
>   read from socket theIPAddress for thePacketSize chars
>   put the result into myResult
>   put it into myPacketData
>
Note this is a blocking read. That will normally work OK (since the 
client sends the packet size followed by the data), but it is not 
robust. If the client was forced to split the data into different 
packets (e.g. if the data was relatively large), and the subsequent 
packet was lost in the network (i.e needed to be NAK'ed and then 
retransmitted), then this could cause your handler to block for an 
arbitrarily long period - up to the timeout interval.

It's up to you, but I would NEVER do a blocking read - I'd simply do

   read from socket theIPAddress for thePacketSize chars with message 
"ServerReceivedPacketData"

and put most of the following code into that new handler (finishing, of 
course with another "read from ... ServerReceivedPacketSize")
>   get DebugLogString("ServerReceivedPacketSize, Packet Data:" && 
> myPacketData && myResult)
>
>   if myResult <> empty then
>     get DebugLogString("ServerReceivedPacketSize, Error:" && myResult)
>     breakpoint
>   end if
>
>   --
>   --  Get the Message Content
>   --
>   put item 1 of myPacketData into myPacketID
>   put item 2 of myPacketData into myPacketCommand
>
>   if myPacketID = "$SYS" then
>     if myPacketCommand = "Connect" then
>       put item 3 of myPacketData into myConnectionID
>
>      end if
>
>   end if
>
> end ServerReceivedPacketSize
>
>
> --  StartClient
>
> function StartClient theServerList,theConnectionID
>
>   set the socketTimeoutInterval to (2 * 1000)
>   put theServerList into sgConnectToServerList
>   repeat for each line myIPAddress in sgConnectToServerList
>     send "StartOneClient myIPAddress,theConnectionID" to me in 0 seconds
>   end repeat
>
>   return empty
> end StartClient
>
I notice that StartOneClient really only does 'open socket' (which is 
non-blocking, since you specify a callback handler) and therefore is 
very quick, so unless you expect very large lists of servers, you could 
simplify this and not bother with the send message, just call the 
handler directly. No problem doing it the way you have done - just want 
to point out the non-blocking (and hence speedy) nature of "open socket".
>
>
> --  StartOneClient
>
> on StartOneClient theIPAddress,theConnectionID
>   local myServerIPAddress
>   local myServerPortNumber
>   local mySocketAddress
>   local myConnectString
>   local myPacketSize
>   local myResult
>
>   put 
> _DecodeIPAddress(theIPAddress,myServerIPAddress,myServerPortNumber) 
> into myResult
>   if myResult <> empty then
>     get DebugLogString("StartOneClient - IP Address Error:" && 
> theIPAddress && myResult)
>     breakpoint
>     exit StartOneClient
>   end if
>
>    put myServerIPAddress & ":" & myServerPortNumber & "|" & 
> theConnectionID into mySocketAddress
>
>   get DebugLogString("StartOneClient - Connect:" && mySocketAddress && 
> myResult)
>
>   open socket mySocketAddress with message "ClientSocketOpen"
>   put the result into myResult
I don't believe 'the result' has anything useful here, since you 
specified a callback handler.
>   if myResult <> empty then
>     get DebugLogString("StartOneClient - Write Socket Count Error:" && 
> mySocketAddress && myPacketSize && myResult)
>     breakpoint
>     exit StartOneClient
>   end if
>
> end StartOneClient


-- 

Alex Tweedly      mailto:alex at tweedly.net      www.tweedly.net




More information about the use-livecode mailing list