Erik,

Yes, I saw your previous email, answering it was on my todo list ;-)

I took Pharo 9 on macOS 10.15 and did:

Metacello new
  repository: 'github://svenvc/zinc/repository';
  baseline: 'ZincHTTPComponents';
  load: #(WebSocket).

(Accepting loads over existing code)

Although your example is clear, and I could run it, it is still a bit unclear 
to me what you actually want to do architecturally.

Indeed, it takes 30s (the timeout) for the reading on the client side (inside 
the #runWith:) to react to the closing in the case of ZnWebSocket>>#close 
(which sends #close to the stream/socket).

Your alternative works, because in that case, the other end (server side) 
closes, which apparently triggers the reading on the client side out of its 
timeout.

Why this does not work is not clear to me (note the 2 process interact with the 
socket).

There are several ways to change the timeout, the simplest is globally doing:

ZnNetworkingUtils defaultSocketStreamTimeout: 5.

But it would be better to do it dynamically (that is possible but another 
story).

Anyway changing the timeout to 5s and logging the time using:

| server client | 
server := ZnWebSocket startServerOn: 1701 do: [ :webSocket | 
       [ webSocket runWith: [ :message | Transcript show: 'Received message: ', 
message 
printString ; cr ] ] 
       on: ConnectionClosed, PrimitiveFailed do: [ "ignore close" ]. 
       Transcript show: 'The server is closed @' , DateAndTime now asString; cr 
]. 
client := ZnWebSocket to: (ZnUrl fromString: 'ws://localhost:1701'). 
[ 
       [ client runWith: [ :message | "ignore received messages" ] ] 
       on: ConnectionClosed, PrimitiveFailed do: [ "ignore close" ]. 
       Transcript show: 'The client is closed@' , DateAndTime now asString; cr. 
       server stop ] fork. 
(Delay forSeconds: 1) wait. 
client sendMessage: 'Hello world'. 
client close. 
"Workaround: use the following instead of 'client close'."
"client sendFrame: ZnWebSocketFrame close."
{ server. client }.

Shows indeed the difference between 30s and 5s.

Now, if you only want to send a message, why not do:

| server client | 
ZnNetworkingUtils defaultSocketStreamTimeout: 5.
server := ZnWebSocket startServerOn: 1701 do: [ :webSocket | 
        [ 
                webSocket runWith: [ :message | 
                        Transcript show: 'Received message: ', message 
printString ; cr ] ] 
                on: ConnectionClosed, PrimitiveFailed do: [ "ignore close" ]. 
        Transcript show: 'Server websocket closed @' , DateAndTime now 
asString; cr ]. 
client := ZnWebSocket to: 'ws://localhost:1701'. 
client sendMessage: 'Hello world'. 
client close. 
{ server. client }.

This works fine/immediately (since there is no pending read to interact with).

That is why I was asking what your architecture is.

Because if you want to do asynchronous reading and writing, from different 
processes, things will inevitably get more complicated.

BTW: the server does not close, just the server side web socket.

Sven

> On 2 Jun 2020, at 19:06, Erik Stel <erik.s...@gmail.com> wrote:
> 
> Hi Sven,
> 
> Maybe you missed the additional post with the source code (I attached it
> again below with small change in way it is logging). Is there any advice on
> how to do this (other than the workaround I'm using at the moment)? The
> issue being that the client recognises its own closing only after a timeout
> (around 30 seconds by default). A message "Client closed" will appear on the
> Transcript after this 30 seconds. With the workaround (see comment in code),
> it does recognise the closing immediately.
> 
> As you can see, I'm already using #runWith: as you suggested. Your recent
> addition of sending 'ping' does not change the synchronous behaviour.
> 
> I'm using this on a Pharo 7 image, but also tested it on Pharo 9.
> 
> Kind regards,
> Erik
> 
> Just in case, I added the code again (without using #crLog: this time):
> 
> | server client | 
> server := ZnWebSocket startServerOn: 1701 do: [ :webSocket | 
>        [ webSocket runWith: [ :message | Transcript show: 'Received
> message: ', message 
> printString ; cr ] ] 
>        on: ConnectionClosed, PrimitiveFailed do: [ "ignore close" ]. 
>        Transcript show: 'The server is closed' ; cr ]. 
> client := ZnWebSocket to: (ZnUrl fromString: 'ws://localhost:1701'). 
> [ 
>        [ client runWith: [ :message | "ignore received messages" ] ] 
>        on: ConnectionClosed, PrimitiveFailed do: [ "ignore close" ]. 
>        Transcript show: 'The client is closed' ; cr. 
>        server stop ] fork. 
> (Delay forSeconds: 1) wait. 
> client sendMessage: 'Hello world'. 
> client close. 
> "Workaround: use the following instead of 'client close'. 
> client sendFrame: ZnWebSocketFrame close." 
> 
> 
> 
> 
> 
> --
> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
> 


Reply via email to