ServerSocket.cs 3.8 KB
Newer Older
cann-alberto's avatar
cann-alberto committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
using ReadyPlayerMe.Core;
using System;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;


public class ServerSocket : MonoBehaviour
{
    private TcpListener _server;
    private TcpClient _client;
    private NetworkStream _stream;
    private bool _isRunning = false;

    private ConcurrentQueue<MessageInfo> messageQueue = new ConcurrentQueue<MessageInfo>(); // Thread-safe queue

    public event Action<MessageInfo> OnMessageReceived;
    public void StartServer(int port)
    {
        try
        {
            _server = new TcpListener(IPAddress.Any, port);
            _server.Start();
            _isRunning = true;
            Debug.Log("Server socket started. Waiting for client...");
            _server.BeginAcceptTcpClient(OnClientConnected, null);
        }
        catch (Exception ex)
        {
            Debug.LogError("Server error: " + ex.Message);
        }
    }

    void OnClientConnected(IAsyncResult result)
    {
        if (!_isRunning) return;
        
        _client = _server.EndAcceptTcpClient(result);
        _stream = _client.GetStream();
        Debug.Log("Client connected!");
        ReceiveMessage();
    }

    void ReceiveMessage()
    {        
        if (_stream == null || !_stream.CanRead)
            return; // Prevent issues if the stream is closed                    

        byte[] buffer = new byte[1024];
        _stream.BeginRead(buffer, 0, buffer.Length, ar =>
        {
            try
            {
                int bytesRead = _stream.EndRead(ar);                
                if (bytesRead > 0)
                {
                    string responseText = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    MessageInfo message = JsonUtility.FromJson<MessageInfo>(responseText);
                    messageQueue.Enqueue(message);
                    
                }
                
                // Closing current connection
                _client.Close();
                _stream.Close();                
                _server.BeginAcceptTcpClient(OnClientConnected, null);
            }
            catch (Exception ex)
            {
                Debug.LogError("Error reading from stream: " + ex.Message);
            }
        }, null);
    }
   
    public void SendSocketMessage(string message)
    {
        if (_stream != null && _stream.CanWrite)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(message);
            _stream.BeginWrite(buffer, 0, buffer.Length, OnWriteComplete, null);
            Debug.Log("Message sent: " + message);
        }
    }

    private void OnWriteComplete(IAsyncResult ar)
    {
        try
        {
            _stream.EndWrite(ar); // Completes the async write operation
            Debug.Log("Message write completed.");
        }
        catch (Exception ex)
        {
            Debug.LogError("Error writing to stream: " + ex.Message);
        }
    }

    void OnDestroy()
    {
cann-alberto's avatar
cann-alberto committed
102
        // TODO: Close the server socket only when the entire application was closed, not only the current scene
cann-alberto's avatar
cann-alberto committed
103
104
105
        //isRunning = false;
        //stream?.Close();
        //client?.Close();
cann-alberto's avatar
cann-alberto committed
106
        //server?.Stop();        
cann-alberto's avatar
cann-alberto committed
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
    }

    private void Update()
    {
        // Process messages from the queue on the main thread
        if (messageQueue.TryDequeue(out MessageInfo message))
        {            
            OnMessageReceived?.Invoke(message);
        }
    }
}

[Serializable]
public class MessageInfo
{
    public DateTime time;
    public string source;
    public string destination;
cann-alberto's avatar
cann-alberto committed
125
    public string body;    
cann-alberto's avatar
cann-alberto committed
126
127
    

cann-alberto's avatar
cann-alberto committed
128
    public MessageInfo(DateTime time, string source, string destination, string body)
cann-alberto's avatar
cann-alberto committed
129
130
131
132
    {
        this.time = time;
        this.source = source;
        this.destination = destination;
cann-alberto's avatar
cann-alberto committed
133
        this.body = body;        
cann-alberto's avatar
cann-alberto committed
134
135
136
    }
     
}