source: 2015/koodauskerho/sieerinn/TasohyppelyNettipeli/TasohyppelyNettipeli/TasohyppelyNettipeli/NetworkConnection.cs @ 7144

Revision 7144, 6.0 KB checked in by otjojunt, 5 years ago (diff)

Käyttäjälle järkevän oloinen ilmoitus jos yhdistäminen ei onnistu.

Line 
1using System;
2using System.IO;
3using System.Linq;
4using System.Net;
5using System.Net.Sockets;
6using System.Reflection;
7using System.Runtime.Serialization;
8using System.Threading;
9using System.Runtime.Serialization.Formatters.Binary;
10using System.Text;
11
12
13public class NetworkConnection
14{
15    sealed class AssemblyBinder : SerializationBinder
16    {
17        public override Type BindToType(string assemblyName, string typeName)
18        {
19            return Type.GetType(String.Format("{0}, {1}", typeName, Assembly.GetExecutingAssembly().FullName));
20        }
21    }
22
23    private const int BLOCK_SIZE = 2048;
24
25    private readonly byte[] guidBytes;
26    private readonly TcpClient client;
27    private readonly CancellationTokenSource cancelSource;
28    private readonly string gameName;
29    private NetworkStream networkStream;
30    private Thread receiveThread;
31
32    public delegate void MessageReceived(Guid id, string message);
33    public delegate void ConnectionChanged(Guid id);
34
35    public event MessageReceived OnMessageReceive;
36    public event ConnectionChanged OnConnect;
37    public event ConnectionChanged OnDisconnect;
38
39    public bool Connected { get; private set; }
40
41    public enum MessageType
42    {
43        Connected = 0, Disconnected, Message
44    }
45
46    public NetworkConnection(string gameName)
47    {
48        Connected = false;
49        this.gameName = gameName;
50        var guid = Guid.NewGuid();
51        guidBytes = guid.ToByteArray();
52        cancelSource = new CancellationTokenSource();
53        client = new TcpClient();
54    }
55
56    public bool Connect(string ip, int port)
57    {
58        try
59        {
60            client.Connect(ip, port); // TODO: try
61        } catch (SocketException ex)
62        {
63            return false;
64        }
65        networkStream = client.GetStream();
66        receiveThread = new Thread(() => ReceiveThread(cancelSource.Token));
67        receiveThread.Start();
68        Connected = true;
69        Send(MessageType.Connected);
70        return true;
71    }
72
73    public void Close()
74    {
75        if (!Connected) return;
76        Send(MessageType.Disconnected);
77        cancelSource.Cancel();
78        receiveThread.Join();
79        networkStream.Close();
80        client.Client.Close();
81        client.Close();
82        Connected = false;
83    }
84
85    private void Send(MessageType type, string message = "")
86    {
87        //var mstream = new MemoryStream();
88        //var writer = new BinaryWriter(mstream);
89
90        //writer.Write((byte)type);
91        //writer.Write(guidBytes, 0, guidBytes.Length);
92        //writer.Write(gameName);
93        //if (message.Length > 0)
94        //    writer.Write(message);
95
96        //var sendBytes = mstream.ToArray();
97        //var lengthBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(sendBytes.Length));
98
99        //networkStream.Write(lengthBytes, 0, lengthBytes.Length);
100        //networkStream.Write(sendBytes, 0, sendBytes.Length);
101        //networkStream.Flush();
102
103        var builder = new StringBuilder();
104
105        builder.Append((int)type);
106        builder.Append('\x01');
107
108        builder.Append(Convert.ToBase64String(guidBytes));
109        builder.Append('\x01');
110
111        builder.Append(gameName);
112        builder.Append('\x01');
113
114        if (message.Length > 0)
115        {
116            builder.Append(message);
117            builder.Append('\x01');
118        }
119
120        builder.Append('\x00');
121
122        var bytes = Encoding.ASCII.GetBytes(builder.ToString());
123        networkStream.Write(bytes, 0, bytes.Length);
124        networkStream.Flush();
125    }
126
127    public void SendMessage(string message)
128    {
129        Send(MessageType.Message, message);
130    }
131
132    public T DeserializeFromString<T>(string settings) where T : class
133    {
134        var bytes = Convert.FromBase64String(settings);
135        using (var mstream = new MemoryStream(bytes))
136        {
137            var formatter = new BinaryFormatter();
138            formatter.Binder = new AssemblyBinder();
139            mstream.Seek(0, SeekOrigin.Begin);
140            return formatter.Deserialize(mstream) as T;
141        }
142    }
143
144    public void SendObject(object serializableObject)
145    {
146        using (var mstream = new MemoryStream())
147        {
148            var formatter = new BinaryFormatter();
149            formatter.Serialize(mstream, serializableObject);
150            mstream.Flush();
151            mstream.Position = 0;
152            SendMessage(Convert.ToBase64String(mstream.ToArray()));
153        }
154    }
155
156    private void ParsePacket(string packet)
157    {
158        var parts = packet.Split('\x01');
159
160        var messageType = (MessageType)int.Parse(parts[0]);
161        var senderGuid = new Guid(Convert.FromBase64String(parts[1]));
162        var game = parts[2];
163
164        if (messageType == MessageType.Message && OnMessageReceive != null)
165        {
166            var message = parts[3];
167            OnMessageReceive(senderGuid, message);
168        }
169        else if (messageType == MessageType.Connected && OnConnect != null)
170        {
171            OnConnect(senderGuid);
172        }
173        else if (messageType == MessageType.Disconnected && OnDisconnect != null)
174        {
175            OnDisconnect(senderGuid);
176        }
177    }
178
179    private void ReceiveThread(CancellationToken cancelToken)
180    {
181        var buffer = new StringBuilder();
182
183        while (!cancelToken.IsCancellationRequested)
184        {
185            if (client.Available == 0)
186                continue;
187
188            var receivedBytes = new byte[BLOCK_SIZE];
189            var bytesRead = networkStream.Read(receivedBytes, 0, BLOCK_SIZE);
190
191            for (int i = 0; i < bytesRead; i++)
192            {
193                if (receivedBytes[i] == '\x00')
194                {
195                    ParsePacket(buffer.ToString());
196                    buffer.Clear();
197                }
198                else
199                {
200                    buffer.Append((char)receivedBytes[i]);
201                }
202            }
203        }
204    }
205}
Note: See TracBrowser for help on using the repository browser.