Hello forum,
I was going through the tutorial on sockets (very nice btw, feels so much easier to do TCP servers in this environment then any other language I have used) but there seems to be a problem with the last BlockingCallMonitor tutorial. Everything works fine until I get to the lines: socketA close. socketB close. At this point the image freezes for a minute, then it just beeps on and on forever until I terminate the dolphin image from windows. Any idea what could cause this? Here is the full code listing from the tutorial (the only thing I change is the IP address to 127 0 0 1, since I have no 192 168 0 1 address in use): "Here is the code to set up the Smalltalk Server" serverSocket := ServerSocket port: 2048. acceptanceMonitor := BlockingCallMonitor new. acceptanceMonitor callBlock: [serverSocket accept]. acceptanceMonitor completionBlock: [:socket | serverMonitor := BlockingCallMonitor new. serverMonitor callBlock: [Compiler evaluate: socket receive logged: false]. serverMonitor completionBlock: [:answer | socket send: answer]. serverMonitor errorBlock: [:error | Sound beep. serverMonitor terminate]. serverMonitor monitor ]. acceptanceMonitor monitor. "Client A" socketA := Socket port: 2048 address: (InternetAddress ipAddress: #[192 168 0 1]). socketA connect. socketA send: '5 factorial'; receive. "Display it" "Client B" socketB := Socket port: 2048 address: (InternetAddress ipAddress: #[192 168 0 1]). socketB connect. socketB send: '3+4'; receive. "Display it" socketB send: '((1 to: 10) collect: [:i | i ]) reverse'; receive. "Display it" "Close each client" socketA close. socketB close. |
JasonJ wrote:
> "Here is the code to set up the Smalltalk Server" > serverSocket := ServerSocket port: 2048. > acceptanceMonitor := BlockingCallMonitor new. > acceptanceMonitor callBlock: [serverSocket accept]. > acceptanceMonitor completionBlock: [:socket | > serverMonitor := BlockingCallMonitor new. > serverMonitor callBlock: [Compiler evaluate: socket receive logged: > false]. > serverMonitor completionBlock: [:answer | socket send: answer]. > serverMonitor errorBlock: [:error | Sound beep. serverMonitor > terminate]. > serverMonitor monitor ]. > acceptanceMonitor monitor. The problem here is that the variable used to hold the BlockingCallMonitor for each incoming connection (confusingly called "serverMonitor") is a workspace variable, rather than being local to the #completionBlock: and hence local to each connection. So when B connects, the record of the ongoing connection to A is damaged since the references to "serverSocket" in the orginal monitor's blocks will now refer to the monitor used for B's connection. I'm not sure exactly why that causes the unpleasant symptoms that you see, but that's what's going wrong. If you change the code to: serverSocket := ServerSocket port: 2048. serverMonitor := BlockingCallMonitor new. serverMonitor callBlock: [serverSocket accept]. serverMonitor completionBlock: [:socket || connectionMonitor | connectionMonitor := BlockingCallMonitor new. connectionMonitor callBlock: [Compiler evaluate: socket receive logged: false]. connectionMonitor completionBlock: [:answer | socket send: answer]. connectionMonitor errorBlock: [:error | Sound beep. connectionMonitor terminate]. connectionMonitor monitor]. serverMonitor monitor. then it should work OK. -- chris |
Yes, that fixed it perfectly. Thank you very much. I am a small talk
newbie, but I think this one I should have noticed. Will the documentation be updated to fix errors found by users in the next release? Thanks, Jason Chris Uppal wrote: > JasonJ wrote: > > > "Here is the code to set up the Smalltalk Server" > > serverSocket := ServerSocket port: 2048. > > acceptanceMonitor := BlockingCallMonitor new. > > acceptanceMonitor callBlock: [serverSocket accept]. > > acceptanceMonitor completionBlock: [:socket | > > serverMonitor := BlockingCallMonitor new. > > serverMonitor callBlock: [Compiler evaluate: socket receive logged: > > false]. > > serverMonitor completionBlock: [:answer | socket send: answer]. > > serverMonitor errorBlock: [:error | Sound beep. serverMonitor > > terminate]. > > serverMonitor monitor ]. > > acceptanceMonitor monitor. > > The problem here is that the variable used to hold the BlockingCallMonitor for > each incoming connection (confusingly called "serverMonitor") is a workspace > variable, rather than being local to the #completionBlock: and hence local to > each connection. So when B connects, the record of the ongoing connection to A > is damaged since the references to "serverSocket" in the orginal monitor's > blocks will now refer to the monitor used for B's connection. I'm not sure > exactly why that causes the unpleasant symptoms that you see, but that's what's > going wrong. If you change the code to: > > serverSocket := ServerSocket port: 2048. > serverMonitor := BlockingCallMonitor new. > serverMonitor callBlock: [serverSocket accept]. > serverMonitor completionBlock: [:socket || connectionMonitor | > connectionMonitor := BlockingCallMonitor new. > connectionMonitor callBlock: [Compiler evaluate: socket receive logged: > false]. > connectionMonitor completionBlock: [:answer | socket send: answer]. > connectionMonitor errorBlock: [:error | Sound beep. connectionMonitor > terminate]. > connectionMonitor monitor]. > serverMonitor monitor. > > then it should work OK. > > -- chris |
Free forum by Nabble | Edit this page |