You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
5.9 KiB
155 lines
5.9 KiB
2 years ago
|
using System;
|
||
|
// Networking libs
|
||
|
using System.Net;
|
||
|
using System.Net.Sockets;
|
||
|
// For creating a thread
|
||
|
using System.Threading;
|
||
|
// For List & ConcurrentQueue
|
||
|
using System.Collections.Generic;
|
||
|
using System.Collections.Concurrent;
|
||
|
// Unity & Unity events
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Events;
|
||
|
|
||
|
namespace WebSocketServer {
|
||
|
[System.Serializable]
|
||
|
public class WebSocketOpenEvent : UnityEvent<WebSocketConnection> {}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class WebSocketMessageEvent : UnityEvent<WebSocketMessage> {}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class WebSocketCloseEvent : UnityEvent<WebSocketConnection> {}
|
||
|
|
||
|
public class WebSocketServer : MonoBehaviour
|
||
|
{
|
||
|
// The tcpListenerThread listens for incoming WebSocket connections, then assigns the client to handler threads;
|
||
|
private TcpListener tcpListener;
|
||
|
private Thread tcpListenerThread;
|
||
|
private List<Thread> workerThreads;
|
||
|
private TcpClient connectedTcpClient;
|
||
|
|
||
|
public ConcurrentQueue<WebSocketEvent> events;
|
||
|
|
||
|
public string address;
|
||
|
public int port;
|
||
|
public WebSocketOpenEvent onOpen;
|
||
|
public WebSocketMessageEvent onMessage;
|
||
|
public WebSocketCloseEvent onClose;
|
||
|
|
||
|
void Awake() {
|
||
|
if (onMessage == null) onMessage = new WebSocketMessageEvent();
|
||
|
}
|
||
|
|
||
|
void Start() {
|
||
|
events = new ConcurrentQueue<WebSocketEvent>();
|
||
|
workerThreads = new List<Thread>();
|
||
|
|
||
|
tcpListenerThread = new Thread (new ThreadStart(ListenForTcpConnection));
|
||
|
tcpListenerThread.IsBackground = true;
|
||
|
tcpListenerThread.Start();
|
||
|
}
|
||
|
|
||
|
void Update() {
|
||
|
WebSocketEvent wsEvent;
|
||
|
while (events.TryDequeue(out wsEvent)) {
|
||
|
if (wsEvent.type == WebSocketEventType.Open) {
|
||
|
onOpen.Invoke(wsEvent.connection);
|
||
|
this.OnOpen(wsEvent.connection);
|
||
|
} else if (wsEvent.type == WebSocketEventType.Close) {
|
||
|
onClose.Invoke(wsEvent.connection);
|
||
|
this.OnClose(wsEvent.connection);
|
||
|
} else if (wsEvent.type == WebSocketEventType.Message) {
|
||
|
WebSocketMessage message = new WebSocketMessage(wsEvent.connection, wsEvent.data);
|
||
|
onMessage.Invoke(message);
|
||
|
this.OnMessage(message);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void ListenForTcpConnection () {
|
||
|
try {
|
||
|
// Create listener on <address>:<port>.
|
||
|
tcpListener = new TcpListener(IPAddress.Parse(address), port);
|
||
|
tcpListener.Start();
|
||
|
Debug.Log("WebSocket server is listening for incoming connections.");
|
||
|
while (true) {
|
||
|
// Accept a new client, then open a stream for reading and writing.
|
||
|
connectedTcpClient = tcpListener.AcceptTcpClient();
|
||
|
// Create a new connection
|
||
|
WebSocketConnection connection = new WebSocketConnection(connectedTcpClient, this);
|
||
|
// Establish connection
|
||
|
connection.Establish();
|
||
|
// // Start a new thread to handle the connection.
|
||
|
// Thread worker = new Thread (new ParameterizedThreadStart(HandleConnection));
|
||
|
// worker.IsBackground = true;
|
||
|
// worker.Start(connection);
|
||
|
// // Add it to the thread list. TODO: delete thread when disconnecting.
|
||
|
// workerThreads.Add(worker);
|
||
|
}
|
||
|
}
|
||
|
catch (SocketException socketException) {
|
||
|
Debug.Log("SocketException " + socketException.ToString());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// private void HandleConnection (object parameter) {
|
||
|
// WebSocketConnection connection = (WebSocketConnection)parameter;
|
||
|
// while (true) {
|
||
|
// string message = ReceiveMessage(connection.client, connection.stream);
|
||
|
// connection.queue.Enqueue(message);
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
// private string ReceiveMessage(TcpClient client, NetworkStream stream) {
|
||
|
// // Wait for data to be available, then read the data.
|
||
|
// while (!stream.DataAvailable);
|
||
|
// Byte[] bytes = new Byte[client.Available];
|
||
|
// stream.Read(bytes, 0, bytes.Length);
|
||
|
|
||
|
// return WebSocketProtocol.DecodeMessage(bytes);
|
||
|
// }
|
||
|
|
||
|
public virtual void OnOpen(WebSocketConnection connection) {}
|
||
|
|
||
|
public virtual void OnMessage(WebSocketMessage message) {}
|
||
|
|
||
|
public virtual void OnClose(WebSocketConnection connection) {}
|
||
|
|
||
|
public virtual void OnError(WebSocketConnection connection) {}
|
||
|
|
||
|
|
||
|
public void OnDestroy()
|
||
|
{
|
||
|
if (null != tcpListener) {
|
||
|
tcpListenerThread.Abort();
|
||
|
tcpListener.Stop();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// private void SendMessage() {
|
||
|
// if (connectedTcpClient == null) {
|
||
|
// return;
|
||
|
// }
|
||
|
|
||
|
// try {
|
||
|
// // Get a stream object for writing.
|
||
|
// NetworkStream stream = connectedTcpClient.GetStream();
|
||
|
// if (stream.CanWrite) {
|
||
|
// string serverMessage = "This is a message from your server.";
|
||
|
// // Convert string message to byte array.
|
||
|
// byte[] serverMessageAsByteArray = Encoding.ASCII.GetBytes(serverMessage);
|
||
|
// // Write byte array to socketConnection stream.
|
||
|
// stream.Write(serverMessageAsByteArray, 0, serverMessageAsByteArray.Length);
|
||
|
// Debug.Log("Server sent his message - should be received by client");
|
||
|
// }
|
||
|
// }
|
||
|
// catch (SocketException socketException) {
|
||
|
// Debug.Log("Socket exception: " + socketException);
|
||
|
// }
|
||
|
// }
|
||
|
}
|
||
|
}
|
||
|
|