ServerSocket.cs 3.86 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
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;
cann-alberto's avatar
cann-alberto committed
19
    public void StartServer(string ipAddress, int port)
cann-alberto's avatar
cann-alberto committed
20
21
22
    {
        try
        {
cann-alberto's avatar
cann-alberto committed
23
24
            //_server = new TcpListener(IPAddress.Any, port);
            _server = new TcpListener(IPAddress.Parse(ipAddress), port);
cann-alberto's avatar
cann-alberto committed
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
            _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
    }
     
}