kerryjiang / WebSocket4Net

A popular .NET WebSocket Client
Apache License 2.0
764 stars 273 forks source link

websocket4net connect to Java Spring WebSocket server #111

Open jliu1970 opened 6 years ago

jliu1970 commented 6 years ago

Hi Jerry,

Is there any way that the client can connect to Spring WebSocket server?

When I tried with a client instantiated through WebSocket(host, subprotocol, version) { I tried both an empty string and "STOMP" as subprotocol), the client state always transitioned to "Connecting", then "Close".

Thanks Jimmy

jliu1970 commented 6 years ago

I suspect that the Open() method needs to support STOMP's connect frame. But could not figure out a way to pass the frame to Open() method. Thanks Jimmy

jliu1970 commented 6 years ago

Sorry, Kerry. I mistyped your name to Jerry in my initial message. Please advise.

Thanks Jimmy

kerryjiang commented 6 years ago

Could you show me the handshake header the Spring WebSocket server required?

jliu1970 commented 6 years ago

Kerry,

Sorry, it took me a couple of days to get back to you. The following is the capture of the "GET /cadrs/v1/websocket/infor HTTP/1.1" request. Please let me know if this is what you are looking for:

Frame 22: 239 bytes on wire (1912 bits), 239 bytes captured (1912 bits) on interface 6 Ethernet II, Src: IntelCor_68:27:93 (cc:3d:82:68:27:93), Dst: IntelCor_e1:04:3d (cc:3d:82:e1:04:3d) Internet Protocol Version 4, Src: 10.10.29.140, Dst: 10.10.21.208 Transmission Control Protocol, Src Port: 1203, Dst Port: 8080, Seq: 1, Ack: 1, Len: 185 Hypertext Transfer Protocol GET /cadrs/v1/websocket/info HTTP/1.1\r\n User-Agent: Java/1.8.0-internal\r\n Host: 10.10.21.208:8080\r\n Accept: text/html, image/gif, image/jpeg, ; q=.2, /*; q=.2\r\n Connection: keep-alive\r\n \r\n [Full request URI: http://10.10.21.208:8080/cadrs/v1/websocket/info] [HTTP request 1/1] [Response in frame: 23]

kerryjiang commented 6 years ago

It doesn't like a websocket request's information. Websocket request's uri should start with "ws://" or "wss://".

jliu1970 commented 6 years ago

and the [Full request URL: http://10.10.21.208:8080/cadrs/v1/websocket/info] has information of: {"entropy":-1545485823,"origins":[":"],"cookie_needed":true,"websocket":true}

jliu1970 commented 6 years ago

Following by this frame:

Frame 28: 275 bytes on wire (2200 bits), 275 bytes captured (2200 bits) on interface 6 Ethernet II, Src: IntelCor_68:27:93 (cc:3d:82:68:27:93), Dst: IntelCor_e1:04:3d (cc:3d:82:e1:04:3d) Internet Protocol Version 4, Src: 10.10.29.140, Dst: 10.10.21.208 Transmission Control Protocol, Src Port: 1204, Dst Port: 8080, Seq: 1, Ack: 1, Len: 221 Hypertext Transfer Protocol GET /cadrs/v1/websocket/892/2db4d4b8d20842ac9d670fb49a1bf559/websocket HTTP/1.1\r\n Sec-WebSocket-Key: yvAIYYRPv/m+WGKebKeeDQ==\r\n Connection: upgrade\r\n Sec-WebSocket-Version: 13\r\n Host: 10.10.21.208:8080\r\n Upgrade: websocket\r\n \r\n [Full request URI: http://10.10.21.208:8080/cadrs/v1/websocket/892/2db4d4b8d20842ac9d670fb49a1bf559/websocket] [HTTP request 1/1] [Response in frame: 29]

and the [Full request URI:....] has content of "Can "Upgrade" only to "WebSocket"." which the Spring Websocket server response with a 101.

kerryjiang commented 6 years ago

You can use Fiddler instead to capture the raw communication.

It still doesn't seem right: 1) the schema of websocket should be "ws://" and "wss://"; 2) I cannot see any information about "STOMP".

jliu1970 commented 6 years ago

I will try Fiddler and let you know what I get.

Thanks Jimmy

jliu1970 commented 6 years ago

Hi Kerry,

Please see attached for the Fiddler capture. Also, app.zip is the main test client code I used.

Thanks Jimmy

app.zip

FiddlerCaptureWebSocket.zip

jliu1970 commented 6 years ago

Here is a capture through Chrome.

websocketcapture

jliu1970 commented 6 years ago

Hi Kerry,

Please advise if my latest capture included information that you were looking for.

Thanks Jimmy

kerryjiang commented 6 years ago

From the bottom of the screenshot, the server is the RabbitMQ? If so, you have to use a RabbitMQ client instead.

jliu1970 commented 6 years ago

Yea, it is not really intuitive. RabbitMQ really serves as a full function StompBrokerRelay component in the Spring WebSocket solution. From a client point of view, it talks to a websocket server with STOMP subprotocol.

https://www.youtube.com/watch?v=mmIza3L64Ic&feature=c4-overview&list=UU7yfnfvEUlXUIfm8rGLwZdA

Thanks Jimmy

kerryjiang commented 6 years ago

Did you get any detailed error message you you tried to connect with WebSocket4Net?

Try to trace the communication when you connect using websocket4net.

jliu1970 commented 6 years ago

Hi Kerry,

An error was received at the websocket client. Please see the image dump attached for the ErrorEventArgs.

The client constructor looks like: WebSocket webSocketClient = new WebSocket("the server endpoint", "", WebSocketVersion.Rfc6455);

Thanks Jimmy

websocket4neterroreventargs

kerryjiang commented 6 years ago

Could you use Fiddler to track this communication either?

kgqian3910 commented 6 years ago

Hi, Kerry,

My name is Kevin Qian who is working with Jimmy on this issue. Jimmy is out of town for a week. so I can help to collect info you needed.

With fiddler, I don't even see any protocol level packet (HTTP or WS triggered by my client), while I could see in Jimmy's capture when using JS client jimmy attached.

what this link's shown seem matching what we see in JS client: https://tools.ietf.org/html/rfc6455#section-1.3

Regards, Kevin

kgqian3910 commented 6 years ago

I was able to fix the issue on Open() by allowing setAllowedOrigins("") on WebSocket Server side as follows: @Override public void registerStompEndpoints(StompEndpointRegistry registry) { //registry.addEndpoint("/gs-guide-websocket").withSockJS(); //Make sure the endpoint is in sync with the CADRSWebSocketAPI doucment registry.addEndpoint("/cadrs/v1/websocket").withSockJS(); //existing registry registry.addEndpoint("/cadrs/v1/websocket").setAllowedOrigins(""); // newly added registry to fix //Websocket4Net client issue // on Open() } Regards, Kevin

kerryjiang commented 6 years ago

If so, this issue is about origin.

Anyway, you can find what is the correct origin. And set the origin by yourself by the websocket constructor parameter.

var websocket = new WebSocket(xxxx, orgin = "correctOrgin");

kgqian3910 commented 6 years ago

Thank you, that works!

kgqian3910 commented 6 years ago

Hi, Kerry,

One more question for you: Now I am able to connect our Stomp Websocket Server. However, the server will close the endpoint at 30 seconds after the connection is established because the server has heartbeat enabled. Does WebSocket4Net have a way for user to turn on heartbeat? I see that user can set values for EnableAutoSendPing and AutoSendPingInterval. what are the use of these attributes? are they related to heartbeat? Do you have a heartbeat implementation example for a websocket client?

Regards, Kevin

kerryjiang commented 6 years ago

Which kind heartbeat does it want?

If it is just websocket ping/pong, I think websocket4net already enable it by default.

But if it requires some kind application level heart beat, you just need send the the keep alive message following their protocol.