Is there any advantages of having two distinct websocket connections to the same server from the same client? To me this seems a bad design choice, but is there any reason why/where it should work out better?
There are several reasons why you might want to do that but they probably aren't too common (at least not yet):
You have both encrypted and unencrypted data that you are sending/receiving (e.g. some of the data is bulky but not sensitive).
You have both streaming data and latency sensitive data: imagine an interactive game that occasionally has streamed video inside the game. You don't want large media streams to delay receipt of latency sensitive normal game messages.
You have both textual (e.g. JSON control messages) and binary data (typed arrays or blobs) and don't want to bother with adding your own protocol layer to distinguish since WebSockets already does this for you.
You have multiple WebSocket sub-protocols (the optional setting after the URI) that you support and the page wants to access more than one (each WebSocket connection is limited to a single sub-protocol).
You have several different WebSocket services sitting behind the same web server and port. The way the client chooses per connection might depend on URI path, URI scheme (ws or wss), sub-protocol, or perhaps even the first message from client to server.
I'm sure there are other reasons but that's all I can think of off the top of my head.
I found that it can make client logic much simpler when you are only subscribing to updates of certain objects being managed by the server. Instead of devising a custom subscription protocol for a single channel, you can just open a socket for each element.
Let's say you obtained a collection of elements via a REST API at
http://myserver/api/some-elements
You could subscribe to updates of a single element using a socket url like this:
ws://myserver/api/some-elements/42/updates
Of course one can argue that this doesn't scale for complex pages. However, for small and simple appications it might make your life a lot easier.
Related
I am developing a web application where two browsers will need to "connect" to each other in order to play a two-player game.
My initial thoughts on how to go ahead with this were to have one central server, which matches up a pair of clients and acts as a sort of "middleman". When browser A wants to make a move, it sends this to the server. The server then sends it to browser B. From my understanding, this is a typical client-server model.
However, an alternative approach would be to have one browser, e.g browser A that acts as both a server and a client and browser B will only act as a client. When browser A makes a move, it simply sends to brower B, (the client) and vice versa. Every time there is another pair of browsers that connect to play the game, one will act as a server and the other will be just a client.
I thought the second approach could be a peer-to-peer approach, however exactly half the clients will be strictly only be a client so I'm not sure if you can define it as a peer-to-peer model.
So my questions are:
Is there a specific name for the second approach?
What would be the better approach? (given that there isn't much heavy processing and I'm not too worried about scalability as of yet)
I am looking to implement this using javascript and node, and based on that it seems the first approach seems a bit more straightforward, however I cant really justify it apart from that
Browsers cannot host servers. You need to have one central server, as clients cannot connect to each other, and someone needs to serve the webpage itself. Someone needs to port forward, that is the server's job.
For question one, your method doesn’t exist.
For question 2, the best approach is to have the server manage everything. However, you can have the server tell one client to do the calculations and simply forward the packets sent between them. There is no best solution, it depends on how powerful your server is and how demanding your game is.
I would recommend that for a basic game such as connect 4 you have the main server control the actual game, this also prevents cheating. However games like among us with a lot going on will have the server forward stuff between the "host" client and "client" client.
I'm planning to write a real time co-op multiplayer game. Currently I'm in the research phase. I've already written a turn-based game which used websockets and it was working fine.
I haven't tried writing a real time game using this technology however. My questions is about websockets. Is there an alternative way to handle communications between (browser) clients? My idea is to have the game state in each client and only send the deltas to the clients using the server as a mediator/synchronization tool.
My main concern is network speed. I want clients to be able to receive each other's actions as fast as possible so my game can stay real time. I have about 20-30 frames per second with less than a KByte of data per frame (which means a maximum of 20-30 KBytes of data per second per client).
I know that things like "network speed" depend on the connection but I'm interested in the "if all else equals" case.
From a standard browser, a webSocket is going to be your best bet. The only two alternatives are webSocket and Ajax. Both are TCP under the covers so once the connection is established they pretty much offer the same transport. But, a webSocket is a persistent connection so you save connection overhead everytime you want to send something. Plus the persistent connection of the webSocket allows you to send directly from server to client which you will want.
In a typical gaming design, the underlying gaming engine needs to adapt to the speed of the transport between the server and any given client. If the client has a slower connection, then you have to drop the number of packets you send to something that can keep up (perhaps fewer frame updates in your case). The connection speed is what it is so you have to make your app deliver the best experience you can at the speed that there is.
Some other things you can do to optimize the use of the transport:
Collect all data you need to send at one time and send it in one larger send operation rather than lots of small sends. In a webSocket, don't send three separate messages each with their own data. Instead, create one message that contains the info from all three messages.
Whenever possible, don't rely on the latency of the connection by sending, waiting for a response, sending again, waiting for response, etc... Instead, try to parallelize operations so you send, send, send and then process responses as they come in.
Tweak settings for outgoing packets from your server so their is no Nagle delay waiting to see if there is other data to go in the same packet. See Nagle's Algorithm. I don't think you have the ability in a browser to tweak this from the client.
Make sure your data is encoded as efficiently as possible for smallest packet size.
I am running SocketIO on NodeJS and I don't care much about wide browsers support as it's my pet project where I want to use all the power of new technologies to ease the development. My concern is about how I should send large amounts of JSON data from server to client and back. Well, these amounts are not as large as could be for video or image binary data, I suppose not larger than hundreds of kilobytes per request.
Two scenarios I see are:
Send a notification via WebSockets from server to client that some data should be fetched. Then client code runs a regular XHR request to server and gets some data via XHR.
Send the whole data set over WebSockets from server to client. In this case I don't need to run any additional requests - I just get all the data via WebSockets.
I saw first case in Meteor.js, so I wondered the reasons of it.
Please share your opinion.
Websockets should support large data sets (up to 16 exabyte in theory), so from that point of view it should work fine. The advantage of XHR is that you will be able to observe progress over time and in general better tested for large data blocks. For example, I have seen websocket server implementations which (thinking retrospectively) wouldn't handle large data well, because they would load the entire data into memory (rather than streaming the data), but that's of course not necessarily the case for socket.io (dunno). Point in case: try it out with socket.io whilst observing memory usage and stability. If it works, definitely go with websockets, because long term the support for big data packages will only get better and definitely not worse. If it turns out to be unstable or if socket.io can't stream larger data files, then use the XHR construct.
Btw, just a google search turned up siofile, haven't looked into it that much, but it might be just the thing you need.
I currently have a javascript library that is using a JSON file to print them on the screen in an interactive way. (::We are using D3JS Library)
When we are on a client, we can easily delete, edit and create some nodes, that are updated in the JSON every 5-10 seconds.
The problem comes from two main facts :
First the automatic function that call itself every x seconds could make data corruption if we are doing some stuff on the datas already represented on the screen.
Then the project has been made in order to permit 5 people to interact together. When they are present onto the same session we cannot decently make them refresh every 5 seconds, that cause many overhead and doesn't avoid data corruption.
We have mainly thought about a solution only made with javascript and some AJAX but we realize that it should be reconsidered with a trigger that inform the client that the datas are no longer OK.
We are thinking currently about opening a script onto a server in order to attribute on each client an ID.
The goal would be to detect the modification done on the JSON file (on the server). But the point where we are stuck is :
1) Is there a best scripting language to interact server/web?
2) Which type of things should we use to make the clients update their datas? (socket right?)
About the second point the easiest way would be to call a JS function be we aren't aware of the possibilities given by the shell codes...
Sorry about the fact that we are happy developpers but maybe not enough skilled to solve this problem.
Thanks for your helps !
You can achieve that using pure javascript with the new WebSocket feature.
http://www.html5rocks.com/en/tutorials/websockets/basics/
Edit:
WebSocket is a web technology providing full-duplex communications channels over a single TCP connection. The WebSocket API is being standardized by the W3C, and the WebSocket protocol has been standardized by the IETF as RFC 6455.
WebSocket is designed to be implemented in web browsers and web servers, but it can be used by any client or server application. The WebSocket Protocol is an independent TCP-based protocol. Its only relationship to HTTP is that its handshake is interpreted by HTTP servers as an Upgrade request.[1] The WebSocket protocol makes possible more interaction between a browser and a web site, facilitating live content and the creation of real-time games. This is made possible by providing a standardized way for the server to send content to the browser without being solicited by the client, and allowing for messages to be passed back and forth while keeping the connection open.
since I'm using WebSocket connections on more regular bases, I was interested in how things work under the hood. So I digged into the endless spec documents for a while, but so far I couldn't really find anything about chunking the transmission stream itself.
The WebSocket protocol calls it data frames (which describes the pure data stream, so its also called non-control frames). As far as I understood the spec, there is no defined max-length and no defined MTU (maximum transfer unit) value, that in turn means a single WebSocket data-frame may contain, by spec(!), an infinite amount of data (please correct me if I'm wrong here, I'm still a student on this).
After reading that, I instantly setup my little Node WebSocket server. Since I have a strong Ajax history (also on streaming and Comet), my expectations originaly were like, "there must be some kind of interactive mode for reading data while it is transfered". But I am wrong there, ain't I ?
I started out small, with 4kb of data.
server
testSocket.emit( 'data', new Array( 4096 ).join( 'X' ) );
and like expected this arrives on the client as one data-chunk
client
wsInstance.onmessage = function( data ) {
console.log( data.length ); // 4095
};
so I increased the payload and I actually was expecting again, that at some point, the client-side onmessage handler will fire repeatly, effectivley chunking the transmission. But to my shock, it never happened (node-server, tested on firefox, chrome and safari client-side). My biggest payload was 80 MB
testSocket.emit( 'data', new Array( 1024*1024*80 ).join( 'X' ) );
and it still arrived in one big data-chunk on the client. Of course, this takes a while even if you have a pretty good connection. Questions here are
is there any possiblity to chunk those streams, similar to the XHR readyState3 mode ?
is there any size limit for a single ws data-frame ?
are websockets not supposed to transfer such large payloads? (which would make me wonder again why there isn't a defined max-size)
I might still look from the wrong perspective on WebSockets, probably the need for sending large data-amounts is just not there and you should chunk/split any data logically yourself before sending ?
First, you need to differentiate between the WebSocket protocol and the WebSocket API within browsers.
The WebSocket protocol has a frame-size limit of 2^63 octets, but a WebSocket message can be composed of an unlimited number of frames.
The WebSocket API within browsers does not expose a frame-based or streaming API, but only a message-based API. The payload of an incoming message is always completely buffered up (within the browser's WebSocket implementation) before providing it to JavaScript.
APIs of other WebSocket implementations may provide frame- or streaming-based access to payload transferred via the WebSocket protocol. For example, AutobahnPython does. You can read more in the examples here https://github.com/tavendo/AutobahnPython/tree/master/examples/twisted/websocket/streaming.
Disclosure: I am original author of Autobahn and work for Tavendo.
More considerations:
As long as there is no frame/streaming API in browser JS WebSocket API, you can only receive/send complete WS messages.
A single (plain) WebSocket connection cannot interleave the payload of multiple messages. So i.e. if you use large messages, those are delivered in order, and you won't be able to send small messages in between while a big message is still on the fly.
There is an upcoming WebSocket extension (extensions are a builtin mechanism to extend the protocol): WebSocket multiplexing. This allows to have multiple (logical) WebSocket connections over a single underlying TCP connection, which has multiple advantages.
Note also: you can open multiple WS connections (over different underlying TCPs) to a single target server from a single JS / HTML page today.
Note also: you can do "chunking" yourself in application layer: send your stuff in smaller WS messages a reassemble yourself.
I agree, in an ideal world, you'd have message/frame/streaming API in browser plus WebSocket multiplexing. That would give all the power and convenience.
RFC 6455 Section 1.1:
This is what the WebSocket Protocol provides: [...] an alternative to HTTP polling for two-way communication from a web page to a remote server.
As stated, WebSockets are for commmunications between a web page and a server. Please note the difference between a web page and a web browser. Examples being used are browser games and chat applications, who excange many small messages.
If you want to send many MB's in one message, I think you're not using WebSockets the way they were intended. If you want to transfer files, then do so using a Plain Old Http Request, answered with Content-Disposition to let the browser download a file.
So if you explain why you want to send such large amounts of data, perhaps someone can help come up with a more elegant solution than using WebSockets.
Besides, a client or server may refuse too large messages (although it isn't explicitly stated how it'll refuse):
RFC 6455 Section 10.4:
Implementations that have implementation- and/or platform-specific
limitations regarding the frame size or total message size after
reassembly from multiple frames MUST protect themselves against
exceeding those limits. (For example, a malicious endpoint can try
to exhaust its peer's memory or mount a denial-of-service attack by
sending either a single big frame (e.g., of size 2**60) or by sending
a long stream of small frames that are a part of a fragmented
message.) Such an implementation SHOULD impose a limit on frame
sizes and the total message size after reassembly from multiple
frames.