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?

MartyIX
  • 27,828
  • 29
  • 136
  • 207
gman
  • 100,619
  • 31
  • 269
  • 393
  • 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. – Evk May 11 '16 at 11:09
  • 1
    Your error looks like you are trying to close an already closed connection (like client has already closed it at this point). – Evk May 11 '16 at 11:15
  • 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. – gman May 11 '16 at 15:38
  • 1
    out of interest, did you consider alternatives to websocket-sharp? If yes, why did you choose it? I personally use this one http://vtortola.github.io/WebSocketListener/ but maybe you know something that would be useful for me to switch to another one. – Evk May 11 '16 at 15:45
  • @gman 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? – CoffeDeveloper May 11 '16 at 16:59
  • 1
    @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. – gman May 11 '16 at 18:21
  • @evk, I'm using this in Unity3D which only supports .NET 3.5 as of May 2016 – gman May 11 '16 at 18:23
  • @gman 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. :D – CoffeDeveloper May 12 '16 at 08:06
  • 1
    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 designed – gman May 13 '16 at 01:21

1 Answers1

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)

CoffeDeveloper
  • 7,961
  • 3
  • 35
  • 69
  • That is true, and this by this way will call _exactly_ the same code author provides in his example. – Evk May 11 '16 at 11:11
  • 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)`. – gman May 11 '16 at 15:15
  • 1
    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) – CoffeDeveloper May 11 '16 at 15:19
  • 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) – CoffeDeveloper May 11 '16 at 15:20
  • 2
    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. – gman May 11 '16 at 15:23
  • 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? :) – CoffeDeveloper May 11 '16 at 15:26
  • 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. – CoffeDeveloper May 11 '16 at 15:29