ServerSocket.cs 4.17 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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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()
    {
        // TODO Close the server socket only when the entire application was closed, not only the current scene
        //isRunning = false;
        //stream?.Close();
        //client?.Close();
        //server?.Stop();
        Debug.Log("[ON_DESTROY_SERVER_SOCKET]: Server stopped.");
    }

    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;
    public string action;
    public string inItem;
    public string inLocation;
    public string outLocation;
    public string rightsID;
    

    public MessageInfo(DateTime time, string source, string destination, string action, string inItem, string inLocation, string outLocation, string rightsID)
    {
        this.time = time;
        this.source = source;
        this.destination = destination;
        this.action = action;
        this.inItem = inItem;
        this.inLocation = inLocation;
        this.outLocation = outLocation;
        this.rightsID = rightsID;
    }
     
}