Skip to content

Commit 27958ec

Browse files
committed
update session test
1 parent dbd2040 commit 27958ec

File tree

4 files changed

+424
-28
lines changed

4 files changed

+424
-28
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
![](https://img.shields.io/static/v1?label=java&message=1.8&color=blue)
33
![](https://img.shields.io/static/v1?label=spring-boot&message=2.4.5.RELEASE&color=blue)
44
![](https://img.shields.io/static/v1?label=junit&message=4.13.2&color=black)
5+
![](https://img.shields.io/static/v1?label=reconnecting-websocket&color=black)
56

67
### help
78
* https://docs.spring.io/spring-framework/docs/5.3.4/reference/html/web.html#websocket
89
* https://www.ruanyifeng.com/blog/2017/05/websocket.html
10+
* https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
911

1012
### articles
1113
* [使用SpringBoot搭建实时通信服务](https://www.toutiao.com/i7020780189747544609)
Lines changed: 365 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
1+
// MIT License:
2+
//
3+
// Copyright (c) 2010-2012, Joe Walnes
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
//
12+
// The above copyright notice and this permission notice shall be included in
13+
// all copies or substantial portions of the Software.
14+
//
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
// THE SOFTWARE.
22+
23+
/**
24+
* This behaves like a WebSocket in every way, except if it fails to connect,
25+
* or it gets disconnected, it will repeatedly poll until it successfully connects
26+
* again.
27+
*
28+
* It is API compatible, so when you have:
29+
* ws = new WebSocket('ws://....');
30+
* you can replace with:
31+
* ws = new ReconnectingWebSocket('ws://....');
32+
*
33+
* The event stream will typically look like:
34+
* onconnecting
35+
* onopen
36+
* onmessage
37+
* onmessage
38+
* onclose // lost connection
39+
* onconnecting
40+
* onopen // sometime later...
41+
* onmessage
42+
* onmessage
43+
* etc...
44+
*
45+
* It is API compatible with the standard WebSocket API, apart from the following members:
46+
*
47+
* - `bufferedAmount`
48+
* - `extensions`
49+
* - `binaryType`
50+
*
51+
* Latest version: https://github.com/joewalnes/reconnecting-websocket/
52+
* - Joe Walnes
53+
*
54+
* Syntax
55+
* ======
56+
* var socket = new ReconnectingWebSocket(url, protocols, options);
57+
*
58+
* Parameters
59+
* ==========
60+
* url - The url you are connecting to.
61+
* protocols - Optional string or array of protocols.
62+
* options - See below
63+
*
64+
* Options
65+
* =======
66+
* Options can either be passed upon instantiation or set after instantiation:
67+
*
68+
* var socket = new ReconnectingWebSocket(url, null, { debug: true, reconnectInterval: 4000 });
69+
*
70+
* or
71+
*
72+
* var socket = new ReconnectingWebSocket(url);
73+
* socket.debug = true;
74+
* socket.reconnectInterval = 4000;
75+
*
76+
* debug
77+
* - Whether this instance should log debug messages. Accepts true or false. Default: false.
78+
*
79+
* automaticOpen
80+
* - Whether or not the websocket should attempt to connect immediately upon instantiation. The socket can be manually opened or closed at any time using ws.open() and ws.close().
81+
*
82+
* reconnectInterval
83+
* - The number of milliseconds to delay before attempting to reconnect. Accepts integer. Default: 1000.
84+
*
85+
* maxReconnectInterval
86+
* - The maximum number of milliseconds to delay a reconnection attempt. Accepts integer. Default: 30000.
87+
*
88+
* reconnectDecay
89+
* - The rate of increase of the reconnect delay. Allows reconnect attempts to back off when problems persist. Accepts integer or float. Default: 1.5.
90+
*
91+
* timeoutInterval
92+
* - The maximum time in milliseconds to wait for a connection to succeed before closing and retrying. Accepts integer. Default: 2000.
93+
*
94+
*/
95+
(function (global, factory) {
96+
if (typeof define === 'function' && define.amd) {
97+
define([], factory);
98+
} else if (typeof module !== 'undefined' && module.exports){
99+
module.exports = factory();
100+
} else {
101+
global.ReconnectingWebSocket = factory();
102+
}
103+
})(this, function () {
104+
105+
if (!('WebSocket' in window)) {
106+
return;
107+
}
108+
109+
function ReconnectingWebSocket(url, protocols, options) {
110+
111+
// Default settings
112+
var settings = {
113+
114+
/** Whether this instance should log debug messages. */
115+
debug: false,
116+
117+
/** Whether or not the websocket should attempt to connect immediately upon instantiation. */
118+
automaticOpen: true,
119+
120+
/** The number of milliseconds to delay before attempting to reconnect. */
121+
reconnectInterval: 1000,
122+
/** The maximum number of milliseconds to delay a reconnection attempt. */
123+
maxReconnectInterval: 30000,
124+
/** The rate of increase of the reconnect delay. Allows reconnect attempts to back off when problems persist. */
125+
reconnectDecay: 1.5,
126+
127+
/** The maximum time in milliseconds to wait for a connection to succeed before closing and retrying. */
128+
timeoutInterval: 2000,
129+
130+
/** The maximum number of reconnection attempts to make. Unlimited if null. */
131+
maxReconnectAttempts: null,
132+
133+
/** The binary type, possible values 'blob' or 'arraybuffer', default 'blob'. */
134+
binaryType: 'blob'
135+
}
136+
if (!options) { options = {}; }
137+
138+
// Overwrite and define settings with options if they exist.
139+
for (var key in settings) {
140+
if (typeof options[key] !== 'undefined') {
141+
this[key] = options[key];
142+
} else {
143+
this[key] = settings[key];
144+
}
145+
}
146+
147+
// These should be treated as read-only properties
148+
149+
/** The URL as resolved by the constructor. This is always an absolute URL. Read only. */
150+
this.url = url;
151+
152+
/** The number of attempted reconnects since starting, or the last successful connection. Read only. */
153+
this.reconnectAttempts = 0;
154+
155+
/**
156+
* The current state of the connection.
157+
* Can be one of: WebSocket.CONNECTING, WebSocket.OPEN, WebSocket.CLOSING, WebSocket.CLOSED
158+
* Read only.
159+
*/
160+
this.readyState = WebSocket.CONNECTING;
161+
162+
/**
163+
* A string indicating the name of the sub-protocol the server selected; this will be one of
164+
* the strings specified in the protocols parameter when creating the WebSocket object.
165+
* Read only.
166+
*/
167+
this.protocol = null;
168+
169+
// Private state variables
170+
171+
var self = this;
172+
var ws;
173+
var forcedClose = false;
174+
var timedOut = false;
175+
var eventTarget = document.createElement('div');
176+
177+
// Wire up "on*" properties as event handlers
178+
179+
eventTarget.addEventListener('open', function(event) { self.onopen(event); });
180+
eventTarget.addEventListener('close', function(event) { self.onclose(event); });
181+
eventTarget.addEventListener('connecting', function(event) { self.onconnecting(event); });
182+
eventTarget.addEventListener('message', function(event) { self.onmessage(event); });
183+
eventTarget.addEventListener('error', function(event) { self.onerror(event); });
184+
185+
// Expose the API required by EventTarget
186+
187+
this.addEventListener = eventTarget.addEventListener.bind(eventTarget);
188+
this.removeEventListener = eventTarget.removeEventListener.bind(eventTarget);
189+
this.dispatchEvent = eventTarget.dispatchEvent.bind(eventTarget);
190+
191+
/**
192+
* This function generates an event that is compatible with standard
193+
* compliant browsers and IE9 - IE11
194+
*
195+
* This will prevent the error:
196+
* Object doesn't support this action
197+
*
198+
* http://stackoverflow.com/questions/19345392/why-arent-my-parameters-getting-passed-through-to-a-dispatched-event/19345563#19345563
199+
* @param s String The name that the event should use
200+
* @param args Object an optional object that the event will use
201+
*/
202+
function generateEvent(s, args) {
203+
var evt = document.createEvent("CustomEvent");
204+
evt.initCustomEvent(s, false, false, args);
205+
return evt;
206+
};
207+
208+
this.open = function (reconnectAttempt) {
209+
ws = new WebSocket(self.url, protocols || []);
210+
ws.binaryType = this.binaryType;
211+
212+
if (reconnectAttempt) {
213+
if (this.maxReconnectAttempts && this.reconnectAttempts > this.maxReconnectAttempts) {
214+
return;
215+
}
216+
} else {
217+
eventTarget.dispatchEvent(generateEvent('connecting'));
218+
this.reconnectAttempts = 0;
219+
}
220+
221+
if (self.debug || ReconnectingWebSocket.debugAll) {
222+
console.debug('ReconnectingWebSocket', 'attempt-connect', self.url);
223+
}
224+
225+
var localWs = ws;
226+
var timeout = setTimeout(function() {
227+
if (self.debug || ReconnectingWebSocket.debugAll) {
228+
console.debug('ReconnectingWebSocket', 'connection-timeout', self.url);
229+
}
230+
timedOut = true;
231+
localWs.close();
232+
timedOut = false;
233+
}, self.timeoutInterval);
234+
235+
ws.onopen = function(event) {
236+
clearTimeout(timeout);
237+
if (self.debug || ReconnectingWebSocket.debugAll) {
238+
console.debug('ReconnectingWebSocket', 'onopen', self.url);
239+
}
240+
self.protocol = ws.protocol;
241+
self.readyState = WebSocket.OPEN;
242+
self.reconnectAttempts = 0;
243+
var e = generateEvent('open');
244+
e.isReconnect = reconnectAttempt;
245+
reconnectAttempt = false;
246+
eventTarget.dispatchEvent(e);
247+
};
248+
249+
ws.onclose = function(event) {
250+
clearTimeout(timeout);
251+
ws = null;
252+
if (forcedClose) {
253+
self.readyState = WebSocket.CLOSED;
254+
eventTarget.dispatchEvent(generateEvent('close'));
255+
} else {
256+
self.readyState = WebSocket.CONNECTING;
257+
var e = generateEvent('connecting');
258+
e.code = event.code;
259+
e.reason = event.reason;
260+
e.wasClean = event.wasClean;
261+
eventTarget.dispatchEvent(e);
262+
if (!reconnectAttempt && !timedOut) {
263+
if (self.debug || ReconnectingWebSocket.debugAll) {
264+
console.debug('ReconnectingWebSocket', 'onclose', self.url);
265+
}
266+
eventTarget.dispatchEvent(generateEvent('close'));
267+
}
268+
269+
var timeout = self.reconnectInterval * Math.pow(self.reconnectDecay, self.reconnectAttempts);
270+
setTimeout(function() {
271+
self.reconnectAttempts++;
272+
self.open(true);
273+
}, timeout > self.maxReconnectInterval ? self.maxReconnectInterval : timeout);
274+
}
275+
};
276+
ws.onmessage = function(event) {
277+
if (self.debug || ReconnectingWebSocket.debugAll) {
278+
console.debug('ReconnectingWebSocket', 'onmessage', self.url, event.data);
279+
}
280+
var e = generateEvent('message');
281+
e.data = event.data;
282+
eventTarget.dispatchEvent(e);
283+
};
284+
ws.onerror = function(event) {
285+
if (self.debug || ReconnectingWebSocket.debugAll) {
286+
console.debug('ReconnectingWebSocket', 'onerror', self.url, event);
287+
}
288+
eventTarget.dispatchEvent(generateEvent('error'));
289+
};
290+
}
291+
292+
// Whether or not to create a websocket upon instantiation
293+
if (this.automaticOpen == true) {
294+
this.open(false);
295+
}
296+
297+
/**
298+
* Transmits data to the server over the WebSocket connection.
299+
*
300+
* @param data a text string, ArrayBuffer or Blob to send to the server.
301+
*/
302+
this.send = function(data) {
303+
if (ws) {
304+
if (self.debug || ReconnectingWebSocket.debugAll) {
305+
console.debug('ReconnectingWebSocket', 'send', self.url, data);
306+
}
307+
return ws.send(data);
308+
} else {
309+
throw 'INVALID_STATE_ERR : Pausing to reconnect websocket';
310+
}
311+
};
312+
313+
/**
314+
* Closes the WebSocket connection or connection attempt, if any.
315+
* If the connection is already CLOSED, this method does nothing.
316+
*/
317+
this.close = function(code, reason) {
318+
// Default CLOSE_NORMAL code
319+
if (typeof code == 'undefined') {
320+
code = 1000;
321+
}
322+
forcedClose = true;
323+
if (ws) {
324+
ws.close(code, reason);
325+
}
326+
};
327+
328+
/**
329+
* Additional public API method to refresh the connection if still open (close, re-open).
330+
* For example, if the app suspects bad data / missed heart beats, it can try to refresh.
331+
*/
332+
this.refresh = function() {
333+
if (ws) {
334+
ws.close();
335+
}
336+
};
337+
}
338+
339+
/**
340+
* An event listener to be called when the WebSocket connection's readyState changes to OPEN;
341+
* this indicates that the connection is ready to send and receive data.
342+
*/
343+
ReconnectingWebSocket.prototype.onopen = function(event) {};
344+
/** An event listener to be called when the WebSocket connection's readyState changes to CLOSED. */
345+
ReconnectingWebSocket.prototype.onclose = function(event) {};
346+
/** An event listener to be called when a connection begins being attempted. */
347+
ReconnectingWebSocket.prototype.onconnecting = function(event) {};
348+
/** An event listener to be called when a message is received from the server. */
349+
ReconnectingWebSocket.prototype.onmessage = function(event) {};
350+
/** An event listener to be called when an error occurs. */
351+
ReconnectingWebSocket.prototype.onerror = function(event) {};
352+
353+
/**
354+
* Whether all instances of ReconnectingWebSocket should log debug messages.
355+
* Setting this to true is the equivalent of setting all instances of ReconnectingWebSocket.debug to true.
356+
*/
357+
ReconnectingWebSocket.debugAll = false;
358+
359+
ReconnectingWebSocket.CONNECTING = WebSocket.CONNECTING;
360+
ReconnectingWebSocket.OPEN = WebSocket.OPEN;
361+
ReconnectingWebSocket.CLOSING = WebSocket.CLOSING;
362+
ReconnectingWebSocket.CLOSED = WebSocket.CLOSED;
363+
364+
return ReconnectingWebSocket;
365+
});

0 commit comments

Comments
 (0)