77using System . Text . RegularExpressions ;
88// For creating a thread
99using System . Threading ;
10+ // For List & ConcurrentQueue
11+ using System . Collections . Generic ;
12+ using System . Collections . Concurrent ;
1013// Unity & Unity events
1114using UnityEngine ;
1215using UnityEngine . Events ;
@@ -15,14 +18,28 @@ namespace WebSocketServer {
1518 [ System . Serializable ]
1619 public class StringEvent : UnityEvent < string > { }
1720
21+ public struct WebSocketConnection {
22+ public WebSocketConnection ( TcpClient client , NetworkStream stream , ConcurrentQueue < string > queue )
23+ {
24+ this . client = client ;
25+ this . stream = stream ;
26+ this . queue = queue ;
27+ }
28+
29+ public TcpClient client { get ; }
30+ public NetworkStream stream { get ; }
31+ public ConcurrentQueue < string > queue { get ; }
32+ }
33+
1834 public class WebSocketServer : MonoBehaviour
1935 {
36+ // The tcpListenerThread listens for incoming WebSocket connections, then assigns the client to handler threads;
2037 private TcpListener tcpListener ;
2138 private Thread tcpListenerThread ;
39+ private List < Thread > workerThreads ;
2240 private TcpClient connectedTcpClient ;
2341
24- private bool hasNewMessage = false ;
25- private string message = "" ;
42+ private ConcurrentQueue < string > messages ;
2643
2744 public string address ;
2845 public int port ;
@@ -34,50 +51,51 @@ void Awake() {
3451
3552 void Start ( )
3653 {
37- tcpListenerThread = new Thread ( new ThreadStart ( WebSocketServerThread ) ) ;
54+ messages = new ConcurrentQueue < string > ( ) ;
55+ workerThreads = new List < Thread > ( ) ;
56+
57+ tcpListenerThread = new Thread ( new ThreadStart ( ListenForTcpConnection ) ) ;
3858 tcpListenerThread . IsBackground = true ;
3959 tcpListenerThread . Start ( ) ;
4060 }
4161
4262 void Update ( )
4363 {
44- if ( hasNewMessage ) {
64+ string message ;
65+ while ( messages . TryDequeue ( out message ) ) {
4566 onMessage . Invoke ( message ) ;
46- hasNewMessage = false ;
4767 }
4868 }
4969
50- private void WebSocketServerThread ( ) {
70+ private void ListenForTcpConnection ( ) {
5171 try {
5272 // Create listener on <address>:<port>.
5373 tcpListener = new TcpListener ( IPAddress . Parse ( address ) , port ) ;
5474 tcpListener . Start ( ) ;
5575 Debug . Log ( "WebSocket server is listening for incoming connections." ) ;
5676 while ( true ) {
57- using ( connectedTcpClient = tcpListener . AcceptTcpClient ( ) ) {
58- // Get a stream object for reading
59- using ( NetworkStream stream = connectedTcpClient . GetStream ( ) ) {
60- EstablishConnection ( connectedTcpClient , stream ) ;
61- while ( true ) {
62- message = ReceiveMessage ( connectedTcpClient , stream ) ;
63- hasNewMessage = true ;
64- }
65- }
66- }
77+ connectedTcpClient = tcpListener . AcceptTcpClient ( ) ;
78+ NetworkStream stream = connectedTcpClient . GetStream ( ) ;
79+ WebSocketConnection connection = new WebSocketConnection ( connectedTcpClient , stream , messages ) ;
80+ EstablishConnection ( connection ) ;
81+ Thread worker = new Thread ( new ParameterizedThreadStart ( HandleConnection ) ) ;
82+ worker . IsBackground = true ;
83+ worker . Start ( connection ) ;
84+ workerThreads . Add ( worker ) ;
6785 }
6886 }
6987 catch ( SocketException socketException ) {
7088 Debug . Log ( "SocketException " + socketException . ToString ( ) ) ;
7189 }
7290 }
7391
74- private void EstablishConnection ( TcpClient client , NetworkStream stream ) {
92+ private void EstablishConnection ( WebSocketConnection connection ) {
7593 // Wait for enough bytes to be available
76- while ( ! stream . DataAvailable ) ;
77- while ( client . Available < 3 ) ;
94+ while ( ! connection . stream . DataAvailable ) ;
95+ while ( connection . client . Available < 3 ) ;
7896 // Translate bytes of request to string
79- Byte [ ] bytes = new Byte [ client . Available ] ;
80- stream . Read ( bytes , 0 , bytes . Length ) ;
97+ Byte [ ] bytes = new Byte [ connection . client . Available ] ;
98+ connection . stream . Read ( bytes , 0 , bytes . Length ) ;
8199 String data = Encoding . UTF8 . GetString ( bytes ) ;
82100
83101 // Check if the input has a "GET" header. If so, initiate the connection.
@@ -96,11 +114,19 @@ private void EstablishConnection (TcpClient client, NetworkStream stream) {
96114 ) + eol
97115 + eol ) ;
98116
99- stream . Write ( response , 0 , response . Length ) ;
117+ connection . stream . Write ( response , 0 , response . Length ) ;
100118 Debug . Log ( "WebSocket client connected." ) ;
101119 }
102120 }
103121
122+ private void HandleConnection ( object parameter ) {
123+ WebSocketConnection connection = ( WebSocketConnection ) parameter ;
124+ while ( true ) {
125+ string message = ReceiveMessage ( connection . client , connection . stream ) ;
126+ connection . queue . Enqueue ( message ) ;
127+ }
128+ }
129+
104130 private string ReceiveMessage ( TcpClient client , NetworkStream stream ) {
105131 // Wait for data to be available, then read the data.
106132 while ( ! stream . DataAvailable ) ;
0 commit comments