Websocket-sharp is built as a single assembly, websocket-sharp.dll. Websocket-sharp is developed with MonoDevelop. So a simple way to build is to open websocket-sharp.sln and run build for websocket-sharp project with any of the build configurations (e.g. Debug ) in MonoDevelop. (C#) WebSocket Connect. Demonstrates how to establish a WebSocket connection. Once the connection is established, messages may be sent back-and-forth. Websocket-sharp Project ID: 866620 Star 0 1,022 Commits; 4 Branches; 0 Tags; 14.6 MB Files; 14.6 MB Storage; A C# implementation of the WebSocket protocol client. Websocket-Sharp: SignalR: Repository: 3,841 Stars: 8,129 285 Watchers: 695 1,216 Forks: 2,236 - Release Cycle.
-->WebSockets provide a mechanism for fast, secure, two-way communication between a client and a server over the web using HTTP(S), and supporting both UTF-8 and binary messages.
Under the WebSocket Protocol, data is transferred immediately over a full-duplex single socket connection, allowing messages to be sent and received from both endpoints in real time. WebSockets are ideal for use in multiplayer gaming (both real-time and turn-based), instant social network notifications, up-to-date displays of stock or weather information, and other apps requiring secure and fast data transfer.
To establish a WebSocket connection, a specific, HTTP-based handshake is exchanged between the client and the server. If successful, the application-layer protocol is 'upgraded' from HTTP to WebSockets, using the previously established TCP connection. Once this occurs, HTTP is completely out of the picture; data can be sent or received using the WebSocket protocol by both endpoints, until the WebSocket connection is closed.
Note A client cannot use WebSockets to transfer data unless the server also uses the WebSocket protocol. If the server does not support WebSockets, then you must use another method of data transfer.
The Universal Windows Platform (UWP) provides support for both client and server use of WebSockets. The Windows.Networking.Sockets namespace defines two WebSocket classes for use by clients—MessageWebSocket, and StreamWebSocket. Here's a comparison of these two WebSocket classes.
MessageWebSocket | StreamWebSocket |
---|---|
An entire WebSocket message is read/written in a single operation. | Sections of a message can be read with each read operation. |
Suitable when messages are not very large. | Suitable when very large files (such as photos or videos) are being transferred. |
Supports both UTF-8 and binary messages. | Supports only binary messages. |
Similar to a UDP or datagram socket (in the sense of being intended for frequent, small messages), but with TCP's reliability, packet order guarantees, and congestion control. | Similar to a TCP or stream socket. |
Secure your connection with TLS/SSL
In most cases, you'll want to use a secure WebSocket connection so that the data you send and receive is encrypted. This will also increase the chances that your connection will succeed, because many intermediaries such as firewalls and proxies reject unencrypted WebSocket connections. The WebSocket protocol defines these two URI schemes.
URI scheme | Purpose |
---|---|
wss: | Use for secure connections that should be encrypted. |
ws: | Use for unencrypted connections. |
To encrypt your WebSocket connection, use the wss:
URI scheme. Here's an example.
Use MessageWebSocket to connect
MessageWebSocket allows an entire WebSocket message to be read/written in a single operation. Consequently, it's suitable when messages are not very large. The class supports both UTF-8 and binary messages.
The example code below uses the WebSocket.org echo server—a service that echoes back to the sender any message sent to it.
Handle the MessageWebSocket.MessageReceived and MessageWebSocket.Closed events
As shown in the example above, before establishing a connection and sending data with a MessageWebSocket, you should subscribe to the MessageWebSocket.MessageReceived and MessageWebSocket.Closed events.
MessageReceived is raised when data is received. The data can be accessed via MessageWebSocketMessageReceivedEventArgs. Closed is raised when the client or the server closes the socket.
Send data on a MessageWebSocket
Once a connection is established, you can send data to the server. You do this by using the MessageWebSocket.OutputStream property, and a DataWriter, to write the data.
Note The DataWriter takes ownership of the output stream. When the DataWriter goes out of scope, if the output stream is attached to it, the DataWriter deallocates the output stream. After that, subsequent attempts to use the output stream fail with an HRESULT value of 0x80000013. But you can call DataWriter.DetachStream to detach the output stream from the DataWriter and return ownership of the stream to the MessageWebSocket.
Use StreamWebSocket to connect
StreamWebSocket allows sections of a message to be read with each read operation. Consequently, it's suitable when very large files (such as photos or videos) are being transferred. The class supports only binary messages.
The example code below uses the WebSocket.org echo server—a service that echoes back to the sender any message sent to it.
Handle the StreamWebSocket.Closed event
Before establishing a connection and sending data with a StreamWebSocket, you should subscribe to the StreamWebSocket.Closed event. Closed is raised when the client or the server closes the socket.
Send data on a StreamWebSocket
Once a connection is established, you can send data to the server. You do this by using the StreamWebSocket.OutputStream property, and a DataWriter, to write the data.
Note If you want to write more data on the same socket, then be sure to call DataWriter.DetachStream to detach the output stream from the DataWriter before the DataWriter goes out of scope. This returns ownership of the stream to the MessageWebSocket.
Receive data on a StreamWebSocket
Use the StreamWebSocket.InputStream property, and a DataReader, to read the data.
Advanced options for MessageWebSocket and StreamWebSocket
Before establishing a connection, you can set advanced options on a socket by setting properties on either MessageWebSocketControl or StreamWebSocketControl. You access an instance of those classes from the socket object itself either via its MessageWebSocket.Control property or its StreamWebSocket.Control property, as appropriate.
Here's an example using StreamWebSocket. The same pattern applies to MessageWebSocket.
Note Don't try to change a control property after you've called ConnectAsync. The only exception to that rule is MessageWebSocketControl.MessageType.
WebSocket information classes
MessageWebSocket and StreamWebSocket each have a corresponding class that provides additional information about the object.
MessageWebSocketInformation provides information about a MessageWebSocket, and you retrieve an instance of it using the MessageWebSocket.Information property.
StreamWebSocketInformation provides information about a StreamWebSocket, and you retrieve an instance of it using the StreamWebSocket.Information property.
Note that the properties on these information classes are read-only, but you can use them to retrieve information at any time during the lifetime of a web socket object.
Handling exceptions
An error encountered on a MessageWebSocket or StreamWebSocket operation is returned as an HRESULT value. You can pass that HRESULT value to the WebSocketError.GetStatus method to convert it into a WebErrorStatus enumeration value.
Most WebErrorStatus enumeration values correspond to an error returned by the native HTTP client operation. Your app can switch on WebErrorStatus enumeration values to modify app behavior depending on the cause of the exception.
For parameter validation errors, you can use the HRESULT from the exception to learn more detailed information about the error. Possible HRESULT values are listed in Winerror.h
, which can be found in your SDK installation (for example, in the folder C:Program Files (x86)Windows Kits10Includeshared
). For most parameter validation errors, the HRESULT returned is E_INVALIDARG.
Setting timeouts on WebSocket operations
MessageWebSocket and StreamWebSocket use an internal system service to send WebSocket client requests, and to receive responses from a server. The default timeout value used for a WebSocket connect operation is 60 seconds. If the HTTP server that supports WebSockets doesn't or can't respond to the WebSocket connection request (it's temporarily down, or blocked by a network outage), then the internal system service waits the default 60 seconds before it returns an error. That error causes an exception to be thrown on the WebSocket ConnectAsync method. For send and receive operations after a WebSocket connection has been established, the default timeout is 30 seconds.
If the name query for an HTTP server name in the URI returns multiple IP addresses for the name, then the internal system service tries up to 5 IP addresses for the site (each with a default timeout of 60 seconds) before it fails. Consequently, your app could wait several minutes trying to connect to multiple IP addresses before it handles an exception. This behavior might appear to the user like the app has stopped working.
To make your app more responsive and minimize these issues, you can set a shorter timeout on connection requests. You set a timeout in a similar way for both MessageWebSocket and StreamWebSocket.
Important APIs
Related topics
Samples
The Problem: Low Latency Client-Server and Server-Client Connections
The web has been largely built around the so-called request/response paradigm of HTTP. A client loads up a web page and then nothing happens until the user clicks onto the next page. Around 2005, AJAX started to make the web feel more dynamic. Still, all HTTP communication was steered by the client, which required user interaction or periodic polling to load new data from the server.
Technologies that enable the server to send data to the client in the very moment when it knows that new data is available have been around for quite some time. They go by names such as 'Push' or 'Comet'. One of the most common hacks to create the illusion of a server initiated connection is called long polling. With long polling, the client opens an HTTP connection to the server which keeps it open until sending response. Whenever the server actually has new data it sends the response (other techniques involve Flash, XHR multipart requests and so called htmlfiles). Long polling and the other techniques work quite well. You use them every day in applications such as GMail chat.
However, all of these work-arounds share one problem: They carry the overhead of HTTP, which doesn't make them well suited for low latency applications. Think multiplayer first person shooter games in the browser or any other online game with a realtime component.
Introducing WebSocket: Bringing Sockets to the Web
The WebSocket specification defines an API establishing 'socket' connections between a web browser and a server. In plain words: There is an persistent connection between the client and the server and both parties can start sending data at any time.
Getting Started
You open up a WebSocket connection simply by calling the WebSocket constructor:
Notice the ws:
. This is the new URL schema for WebSocket connections. There is also wss:
for secure WebSocket connection the same way https:
is used for secure HTTP connections.
Attaching some event handlers immediately to the connection allows you to know when the connection is opened, received incoming messages, or there is an error.
The second argument accepts optional subprotocols. It can be a string or an array of strings. Each string should represent a subprotocol name and server accepts only one of passed subprotocols in the array. Accepted subprotocol can be determined by accessing protocol
property of WebSocket object.
The subprotocol names must be one of registered subprotocol names in IANA registry. There is currently only one subprotocol name (soap) registered as of February 2012.
Communicating with the Server
As soon as we have a connection to the server (when the open
event is fired) we can start sending data to the server using the send('your message')
method on the connection object. It used to support only strings, but in the latest spec it now can send binary messages too. To send binary data, you can use either Blob
or ArrayBuffer
object.
Equally the server might send us messages at any time. Whenever this happens the onmessage
callback fires. The callback receives an event object and the actual message is accessible via the data
property.
WebSocket can also receive binary messages in the latest spec. Binary frames can be received in Blob
or ArrayBuffer
format. To specify the format of the received binary, set the binaryType property of WebSocket object to either 'blob' or 'arraybuffer'. The default format is 'blob'. (You don't have to align binaryType param on sending.)
Another newly added feature of WebSocket is extensions. Using extensions, it will be possible to send frames compressed, multiplexed, etc. You can find server accepted extensions by examining the extensions property of the WebSocket object after the open event. There is no officially published extensions spec just yet as of February 2012.
Cross Origin Communication
Being a modern protocol, cross origin communication is baked right into WebSocket. While you should still make sure only to communicate with clients and servers that you trust, WebSocket enables communication between parties on any domain. The server decides whether to make its service available to all clients or only those that reside on a set of well defined domains.
Proxy Servers
Every new technology comes with a new set of problems. In the case of WebSocket it is the compatibility with proxy servers which mediate HTTP connections in most company networks. The WebSocket protocol uses the HTTP upgrade system (which is normally used for HTTP/SSL) to 'upgrade' an HTTP connection to a WebSocket connection. Some proxy servers do not like this and will drop the connection. Thus, even if a given client uses the WebSocket protocol, it may not be possible to establish a connection. This makes the next section even more important :)
Use WebSockets Today
WebSocket is still a young technology and not fully implemented in all browsers. However, you can use WebSocket today with libraries that use one of the fallbacks mentioned above whenever WebSocket is not available. A library that has become very popular in this domain is socket.io which comes with a client and a server implementation of the protocol and includes fallbacks (socket.io doesn't support binary messaging yet as of Februrary 2012). There are also commercial solutions such as PusherApp which can be easily integrated into any web environment by providing a HTTP API to send WebSocket messages to clients. Due to the extra HTTP request there will always be extra overhead compared to pure WebSocket.
Websocket Client
The Server Side
Receive data on a StreamWebSocket
Use the StreamWebSocket.InputStream property, and a DataReader, to read the data.
Advanced options for MessageWebSocket and StreamWebSocket
Before establishing a connection, you can set advanced options on a socket by setting properties on either MessageWebSocketControl or StreamWebSocketControl. You access an instance of those classes from the socket object itself either via its MessageWebSocket.Control property or its StreamWebSocket.Control property, as appropriate.
Here's an example using StreamWebSocket. The same pattern applies to MessageWebSocket.
Note Don't try to change a control property after you've called ConnectAsync. The only exception to that rule is MessageWebSocketControl.MessageType.
WebSocket information classes
MessageWebSocket and StreamWebSocket each have a corresponding class that provides additional information about the object.
MessageWebSocketInformation provides information about a MessageWebSocket, and you retrieve an instance of it using the MessageWebSocket.Information property.
StreamWebSocketInformation provides information about a StreamWebSocket, and you retrieve an instance of it using the StreamWebSocket.Information property.
Note that the properties on these information classes are read-only, but you can use them to retrieve information at any time during the lifetime of a web socket object.
Handling exceptions
An error encountered on a MessageWebSocket or StreamWebSocket operation is returned as an HRESULT value. You can pass that HRESULT value to the WebSocketError.GetStatus method to convert it into a WebErrorStatus enumeration value.
Most WebErrorStatus enumeration values correspond to an error returned by the native HTTP client operation. Your app can switch on WebErrorStatus enumeration values to modify app behavior depending on the cause of the exception.
For parameter validation errors, you can use the HRESULT from the exception to learn more detailed information about the error. Possible HRESULT values are listed in Winerror.h
, which can be found in your SDK installation (for example, in the folder C:Program Files (x86)Windows Kits10Includeshared
). For most parameter validation errors, the HRESULT returned is E_INVALIDARG.
Setting timeouts on WebSocket operations
MessageWebSocket and StreamWebSocket use an internal system service to send WebSocket client requests, and to receive responses from a server. The default timeout value used for a WebSocket connect operation is 60 seconds. If the HTTP server that supports WebSockets doesn't or can't respond to the WebSocket connection request (it's temporarily down, or blocked by a network outage), then the internal system service waits the default 60 seconds before it returns an error. That error causes an exception to be thrown on the WebSocket ConnectAsync method. For send and receive operations after a WebSocket connection has been established, the default timeout is 30 seconds.
If the name query for an HTTP server name in the URI returns multiple IP addresses for the name, then the internal system service tries up to 5 IP addresses for the site (each with a default timeout of 60 seconds) before it fails. Consequently, your app could wait several minutes trying to connect to multiple IP addresses before it handles an exception. This behavior might appear to the user like the app has stopped working.
To make your app more responsive and minimize these issues, you can set a shorter timeout on connection requests. You set a timeout in a similar way for both MessageWebSocket and StreamWebSocket.
Important APIs
Related topics
Samples
The Problem: Low Latency Client-Server and Server-Client Connections
The web has been largely built around the so-called request/response paradigm of HTTP. A client loads up a web page and then nothing happens until the user clicks onto the next page. Around 2005, AJAX started to make the web feel more dynamic. Still, all HTTP communication was steered by the client, which required user interaction or periodic polling to load new data from the server.
Technologies that enable the server to send data to the client in the very moment when it knows that new data is available have been around for quite some time. They go by names such as 'Push' or 'Comet'. One of the most common hacks to create the illusion of a server initiated connection is called long polling. With long polling, the client opens an HTTP connection to the server which keeps it open until sending response. Whenever the server actually has new data it sends the response (other techniques involve Flash, XHR multipart requests and so called htmlfiles). Long polling and the other techniques work quite well. You use them every day in applications such as GMail chat.
However, all of these work-arounds share one problem: They carry the overhead of HTTP, which doesn't make them well suited for low latency applications. Think multiplayer first person shooter games in the browser or any other online game with a realtime component.
Introducing WebSocket: Bringing Sockets to the Web
The WebSocket specification defines an API establishing 'socket' connections between a web browser and a server. In plain words: There is an persistent connection between the client and the server and both parties can start sending data at any time.
Getting Started
You open up a WebSocket connection simply by calling the WebSocket constructor:
Notice the ws:
. This is the new URL schema for WebSocket connections. There is also wss:
for secure WebSocket connection the same way https:
is used for secure HTTP connections.
Attaching some event handlers immediately to the connection allows you to know when the connection is opened, received incoming messages, or there is an error.
The second argument accepts optional subprotocols. It can be a string or an array of strings. Each string should represent a subprotocol name and server accepts only one of passed subprotocols in the array. Accepted subprotocol can be determined by accessing protocol
property of WebSocket object.
The subprotocol names must be one of registered subprotocol names in IANA registry. There is currently only one subprotocol name (soap) registered as of February 2012.
Communicating with the Server
As soon as we have a connection to the server (when the open
event is fired) we can start sending data to the server using the send('your message')
method on the connection object. It used to support only strings, but in the latest spec it now can send binary messages too. To send binary data, you can use either Blob
or ArrayBuffer
object.
Equally the server might send us messages at any time. Whenever this happens the onmessage
callback fires. The callback receives an event object and the actual message is accessible via the data
property.
WebSocket can also receive binary messages in the latest spec. Binary frames can be received in Blob
or ArrayBuffer
format. To specify the format of the received binary, set the binaryType property of WebSocket object to either 'blob' or 'arraybuffer'. The default format is 'blob'. (You don't have to align binaryType param on sending.)
Another newly added feature of WebSocket is extensions. Using extensions, it will be possible to send frames compressed, multiplexed, etc. You can find server accepted extensions by examining the extensions property of the WebSocket object after the open event. There is no officially published extensions spec just yet as of February 2012.
Cross Origin Communication
Being a modern protocol, cross origin communication is baked right into WebSocket. While you should still make sure only to communicate with clients and servers that you trust, WebSocket enables communication between parties on any domain. The server decides whether to make its service available to all clients or only those that reside on a set of well defined domains.
Proxy Servers
Every new technology comes with a new set of problems. In the case of WebSocket it is the compatibility with proxy servers which mediate HTTP connections in most company networks. The WebSocket protocol uses the HTTP upgrade system (which is normally used for HTTP/SSL) to 'upgrade' an HTTP connection to a WebSocket connection. Some proxy servers do not like this and will drop the connection. Thus, even if a given client uses the WebSocket protocol, it may not be possible to establish a connection. This makes the next section even more important :)
Use WebSockets Today
WebSocket is still a young technology and not fully implemented in all browsers. However, you can use WebSocket today with libraries that use one of the fallbacks mentioned above whenever WebSocket is not available. A library that has become very popular in this domain is socket.io which comes with a client and a server implementation of the protocol and includes fallbacks (socket.io doesn't support binary messaging yet as of Februrary 2012). There are also commercial solutions such as PusherApp which can be easily integrated into any web environment by providing a HTTP API to send WebSocket messages to clients. Due to the extra HTTP request there will always be extra overhead compared to pure WebSocket.
Websocket Client
The Server Side
Using WebSocket creates a whole new usage pattern for server side applications. While traditional server stacks such as LAMP are designed around the HTTP request/response cycle they often do not deal well with a large number of open WebSocket connections. Keeping a large number of connections open at the same time requires an architecture that receives high concurrency at a low performance cost. Such architectures are usually designed around either threading or so called non-blocking IO.
Server Side Implementations
- Node.js
- Java
- Ruby
- Python
- Erlang
- C++
- .NET
Protocol Versions
The wire protocol (a handshake and the data transfer between client and server) for WebSocket is now RFC6455. The latest Chrome and Chrome for Android are fully compatible with RFC6455 including binary messaging. Also, Firefox will be compatible on version 11, Internet Explorer on version 10. You can still use older protocol versions but it is not recommended since they are known to be vulnerable. If you have server implementations for older versions of WebSocket protocol, we recommend you to upgrade it to the latest version.
Use Cases
Websocket Sharp Proxy
Use WebSocket whenever you need a truly low latency, near realtime connection between the client and the server. Keep in mind that this might involve rethinking how you build your server side applications with a new focus on technologies such as event queues. Some example use cases are:
C# Websockets Example
- Multiplayer online games
- Chat applications
- Live sports ticker
- Realtime updating social streams