Using websocket-sharp for .NET how can the server close a WebSocketBehavior?
Asked Answered
S

1

6

I'm trying to use websocket-sharp for a project and the server needs to be able to drop websocket connections.

The connections are represented by a WebSocketBehavior class which you inherit from. There's no Stop or Close or Disconnect method on WebSocketBehavior. The closest I could find is

WebSocketBehavior.Context.WebSocket.Close

So I tried adding a method to my overriding class

public class MySocket : WebSocketBehavior
{
    public void Close()
    {
        base.Context.WebSocket.Close();
    }
}

But that causes an error when logging is turned on

2/5/2016 7:08:25 PM|Error|WebSocket.Close|This operation isn't available in: closed

How can the server disconnect/close a WebSocket connection?

Stat answered 6/2, 2016 at 5:52 Comment(9)
From where do you call that Close() method from your example? Actually for me it works fine. So you may want to provide more details of how you get your error.Ambrogino
Your error looks like you are trying to close an already closed connection (like client has already closed it at this point).Ambrogino
You're correct. @DarioOO's answer though checks if the connection is already closed by checking if the given id is in the list of sessions.Stat
out of interest, did you consider alternatives to websocket-sharp? If yes, why did you choose it? I personally use this one vtortola.github.io/WebSocketListener but maybe you know something that would be useful for me to switch to another one.Ambrogino
@Stat by calling higher level methods you benefit from additional checks without having to re-implement them, developers of WebSocketBehaviour should put more stuff "private" to avoid this issues. maybe do a PR?Spadiceous
@DarioOO you seem to be amazing at understanding bad APIs and how to follow their super obscure higher level methods. Me, I expect an API to make sense. When it doesn't make sense the higher level methods end up being obscured because since they don't make sense there's no way to guess where I should be looking. I'd never guess to look on the Sessions object. In fact I would never have even thought to look for a Sessions object on in individual WebSocketBehavior. Sorry if I'm being defensive but I find it condescending for you to assume I don't know to look for higher level methods.Stat
@evk, I'm using this in Unity3D which only supports .NET 3.5 as of May 2016Stat
@Stat sorry I didn't intended to be offensive, my conclusions where simply based on "dependency depth", The more the dependencies I have to disclose/traverse to access something, higher the "code smell". when I find myself doing stuff like A.B.C.D then I start thinking I should not do that and my laziness force me to find an "easier" way, so yeah I'm amazing at being lazy. :DSpadiceous
Yea, and that's why I asked the question since A.B.C.D seemed wrong but there was no clear way to do it because the API is poorly designedStat
S
2

As stated from a ticket in their repo

You just need to close the related session:

 Sessions.CloseSession(ID);

EDIT:

It is the same code as the OP but called through correct abstractions, that should work in theory, however the fact that he tries to access stuff from "low level", made me to suspect that he access other internal functionality all bypassing "public method" wich could results in wrong behaviour (like stuff called by "public methods" no longer working, I suggest you access everything only from proper abstractions in order to avoid problems, after that if the problem persist you should make a ticket asking for a bugfix in the original repository. Such a bug cannot by fixed there becuse require to be aware of all other the code written by you.

After that you should track both client and server side with a log file to discover what happens, in example connection already closed by client (as stated by Evk in comments)

Spadiceous answered 11/5, 2016 at 11:10 Comment(7)
That is true, and this by this way will call exactly the same code author provides in his example.Ambrogino
Thanks. I'm not so sure about correct abstractions. The docs are short and the readme example shows talking to a socket through methods of an overridden WebSocketBehavior. Having to go through Sessions & ID seems like a completely wrong headed abstraction. Why does a single socket care about sessions and id? It just wants to close itself. It shouldn't have to distinguish between itself and other sessions. Take File for example. It's File.Close not FileSystem.CloseFile(someFile.ID). So it was not clear whatsoever the correct abstraction is this.Sessions.CloseSession(this.ID).Stat
By correct abstraction I mean that one should try to use highest-level possible methods without having to access internal properties, I'm not saying in any way that the library is designed in the same way I would design it or there exist a good way to use it, however hoping that the developer followed at least some of good programming principles, you should agree that in general is bad going to access "member, inside member" for calling a method, and if possible should be done by using higher-level methods (encapsulation and information hiding)Spadiceous
In example to me the library is just a mess, because it allows to access almost everything from the behaviour, allowing users to do the changes they want and causing an avalanche of side effects that are far from being able to be tested in a complete way. When doing "bad" things at least a developer should leave a document/rational explaining why he did something bad but wich other problems he solved by doing that. (I not pretend to have everything documented, but at least important decisions should)Spadiceous
I agree with you but poor API design means it's not clear whatsoever that those abstractions even exist. If I have a File I wouldn't expect to find a OpenFiles property on File to which I can pass some id that happens to be on a property called ID given that it makes no sense for a File to have either of those properties. My point is telling me I should follow correct abstractions assumes that there's any reason for me to even expect those abstractions to exist in the first place. I can't divine that Sessions is even something I should care about.Stat
It is the same I thinked, however there's a explicit comment by developer that you can use session to close a connection wich I took as "documentation". .. Just guessing eh ^^. does my code snippet works at least? :)Spadiceous
As side note, whatever "Behaviour" (anti)pattern is just about mixing all responsibilities into the same class by adding lots of methods or at least by injectin as properties global objects (in this case Sessions). It is far easy falling into troubles with "Behaviours".. Unity3D do the same in example, and many people complain about that.Spadiceous

© 2022 - 2024 — McMap. All rights reserved.