-
Notifications
You must be signed in to change notification settings - Fork 699
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[unity]添加websocket的支持(默认没有编译,需要的话加--websocket)
- Loading branch information
1 parent
1425096
commit 223be87
Showing
11 changed files
with
710 additions
and
6 deletions.
There are no files selected for viewing
143 changes: 143 additions & 0 deletions
143
unity/Assets/core/upm/Runtime/Resources/puerts/websocketpp.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/* | ||
* Tencent is pleased to support the open source community by making Puerts available. | ||
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. | ||
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may be subject to their corresponding license terms. | ||
* This file is subject to the terms and conditions defined in file 'LICENSE', which is part of this source code package. | ||
*/ | ||
|
||
var global = global || globalThis || (function () { return this; }()); | ||
|
||
const WebSocketPP = global.WebSocketPP; | ||
//global.WebSocketPP = undefined; | ||
|
||
class EventTarget { | ||
constructor() { | ||
this.listeners = {}; | ||
} | ||
|
||
addEventListener(type, callback) { | ||
if (!(type in this.listeners)) { | ||
this.listeners[type] = []; | ||
} | ||
this.listeners[type].push(callback); | ||
} | ||
|
||
removeEventListener(type, callback) { | ||
if (!(type in this.listeners)) { | ||
return; | ||
} | ||
const stack = this.listeners[type]; | ||
for (let i = 0; i < stack.length; i++) { | ||
if (stack[i] === callback) { | ||
stack.splice(i, 1); | ||
return; | ||
} | ||
} | ||
} | ||
|
||
dispatchEvent(ev) { | ||
if (!(ev.type in this.listeners)) { | ||
return true; | ||
} | ||
const stack = this.listeners[ev.type].slice(); | ||
|
||
for (let i = 0; i < stack.length; i++) { | ||
stack[i].call(this, ev); | ||
} | ||
return !ev.defaultPrevented; | ||
} | ||
} | ||
|
||
const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']; | ||
|
||
const poll_ws_objects = []; | ||
|
||
class WebSocket extends EventTarget { | ||
constructor(url, protocols) { | ||
super(); | ||
if (protocols) throw new Error('do not support protocols argument'); | ||
this._raw = new WebSocketPP(url); | ||
this._url = url; | ||
// !!do not raise exception in handles. | ||
this._raw.setHandles( | ||
()=> { | ||
this._readyState = WebSocket.OPEN; | ||
this._addPendingEvent({type:'open'}); | ||
}, | ||
(data) => { | ||
this._addPendingEvent({type:'message', data:data, origin:this._url}); | ||
}, | ||
(code, reason) => { | ||
this._cleanup(); | ||
this._addPendingEvent({type:'close', code:code, reason: reason}); | ||
}, | ||
() => { | ||
this._addPendingEvent({type:'error'}); | ||
this._cleanup(); | ||
this._addPendingEvent({type:'close', code:1006, reason: ""}); | ||
}); | ||
|
||
this._readyState = WebSocket.CONNECTING; | ||
this._tid = setInterval(() => this._poll(), 1); | ||
this._pendingEvents = []; | ||
} | ||
|
||
get url() { | ||
return this._url; | ||
} | ||
|
||
get readyState() { | ||
return this._readyState; | ||
} | ||
|
||
send(data) { | ||
if (this._readyState !== WebSocket.OPEN) { | ||
throw new Error(`WebSocket is not open: readyState ${this._readyState} (${readyStates[this._readyState]})`); | ||
} | ||
this._raw.send(data); | ||
} | ||
|
||
_cleanup() { | ||
this._readyState = WebSocket.CLOSING; | ||
} | ||
|
||
_addPendingEvent(ev) { | ||
this._pendingEvents.push(ev); | ||
} | ||
|
||
_poll() { | ||
if (this._pendingEvents.length === 0 && this._readyState != WebSocket.CLOSING) { | ||
this._raw.poll(); | ||
} | ||
const ev = this._pendingEvents.shift(); | ||
if (ev) this.dispatchEvent(ev); | ||
if (this._pendingEvents.length === 0 && this._readyState == WebSocket.CLOSING) { | ||
this._raw = undefined; | ||
clearInterval(this._tid); | ||
this._readyState = WebSocket.CLOSED; | ||
} | ||
} | ||
|
||
close(code, data) { | ||
try { | ||
this._raw.close(code, data); | ||
} catch(e) {} | ||
this._cleanup(); | ||
} | ||
|
||
} | ||
|
||
for (let i = 0; i < readyStates.length; i++) { | ||
Object.defineProperty(WebSocket, readyStates[i], { | ||
enumerable: true, | ||
value: i | ||
}); | ||
|
||
Object.defineProperty(WebSocket.prototype, readyStates[i], { | ||
enumerable: true, | ||
value: i | ||
}); | ||
} | ||
|
||
global.WebSocket = WebSocket; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
using NUnit.Framework; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
using System.Net; | ||
using System.Net.WebSockets; | ||
using System.Text; | ||
using System.Threading; | ||
|
||
//#if PUERTS_GENERAL | ||
namespace Puerts.UnitTest | ||
{ | ||
|
||
[TestFixture] | ||
public class WebsocketTest | ||
{ | ||
static async Task RunEchoServer() | ||
{ | ||
HttpListener httpListener = new HttpListener(); | ||
httpListener.Prefixes.Add("http://localhost:5000/"); | ||
httpListener.Start(); | ||
Console.WriteLine("Server started at http://localhost:5000/"); | ||
|
||
while (true) | ||
{ | ||
HttpListenerContext httpContext = await httpListener.GetContextAsync(); | ||
|
||
if (httpContext.Request.IsWebSocketRequest) | ||
{ | ||
HttpListenerWebSocketContext webSocketContext = await httpContext.AcceptWebSocketAsync(null); | ||
WebSocket webSocket = webSocketContext.WebSocket; | ||
|
||
await Echo(webSocket); | ||
} | ||
else | ||
{ | ||
httpContext.Response.StatusCode = 400; | ||
httpContext.Response.Close(); | ||
} | ||
} | ||
} | ||
|
||
static async Task Echo(WebSocket webSocket) | ||
{ | ||
byte[] buffer = new byte[1024]; | ||
|
||
while (webSocket.State == WebSocketState.Open) | ||
{ | ||
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); | ||
|
||
if (result.MessageType == WebSocketMessageType.Close) | ||
{ | ||
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None); | ||
} | ||
else | ||
{ | ||
string receivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count); | ||
Console.WriteLine("Received: " + receivedMessage); | ||
|
||
byte[] responseBuffer = Encoding.UTF8.GetBytes(receivedMessage); | ||
await webSocket.SendAsync(new ArraySegment<byte>(responseBuffer), WebSocketMessageType.Text, true, CancellationToken.None); | ||
Console.WriteLine("Echoed: " + receivedMessage); | ||
} | ||
} | ||
} | ||
|
||
[Test] | ||
public void SmokeTest () { | ||
RunEchoServer(); | ||
#if PUERTS_GENERAL | ||
var jsEnv = new JsEnv(new TxtLoader()); | ||
#else | ||
var jsEnv = new JsEnv(new UnitTestLoader()); | ||
#endif | ||
|
||
jsEnv.Eval(@" | ||
(function() { | ||
let con = new WebSocket('ws://localhost:5000'); | ||
con.addEventListener('open', (ev) => { | ||
console.log(`on open`); | ||
con.send('puerts websocket'); | ||
}); | ||
con.addEventListener('message', (ev) => { | ||
console.log(`on message: ${ev.data}`); | ||
global.webSocketMessage = ev.data; | ||
con.close(); | ||
}); | ||
})(); | ||
"); | ||
for(int i =0; i < 20; i++) { | ||
jsEnv.Tick(); | ||
Thread.Sleep(10); | ||
} | ||
|
||
var res = jsEnv.Eval<string>("global.webSocketMessage"); | ||
Assert.AreEqual(res, "puerts websocket"); | ||
} | ||
} | ||
} | ||
//#endif |
Oops, something went wrong.