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

Revision 7143, 5.8 KB checked in by sieerinn, 5 years ago (diff)

Vaihto binääristä tekstimuotoiseen protokollaan.

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 void Connect(string ip, int port)
57    {
58        client.Connect(ip, port); // TODO: try
59        networkStream = client.GetStream();
60        receiveThread = new Thread(() => ReceiveThread(cancelSource.Token));
61        receiveThread.Start();
62        Connected = true;
63        Send(MessageType.Connected);
64    }
65
66    public void Close()
67    {
68        if (!Connected) return;
69        Send(MessageType.Disconnected);
70        cancelSource.Cancel();
71        receiveThread.Join();
72        networkStream.Close();
73        client.Client.Close();
74        client.Close();
75        Connected = false;
76    }
77
78    private void Send(MessageType type, string message = "")
79    {
80        //var mstream = new MemoryStream();
81        //var writer = new BinaryWriter(mstream);
82
83        //writer.Write((byte)type);
84        //writer.Write(guidBytes, 0, guidBytes.Length);
85        //writer.Write(gameName);
86        //if (message.Length > 0)
87        //    writer.Write(message);
88
89        //var sendBytes = mstream.ToArray();
90        //var lengthBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(sendBytes.Length));
91
92        //networkStream.Write(lengthBytes, 0, lengthBytes.Length);
93        //networkStream.Write(sendBytes, 0, sendBytes.Length);
94        //networkStream.Flush();
95
96        var builder = new StringBuilder();
97
98        builder.Append((int)type);
99        builder.Append('\x01');
100
101        builder.Append(Convert.ToBase64String(guidBytes));
102        builder.Append('\x01');
103
104        builder.Append(gameName);
105        builder.Append('\x01');
106
107        if (message.Length > 0)
108        {
109            builder.Append(message);
110            builder.Append('\x01');
111        }
112
113        builder.Append('\x00');
114
115        var bytes = Encoding.ASCII.GetBytes(builder.ToString());
116        networkStream.Write(bytes, 0, bytes.Length);
117        networkStream.Flush();
118    }
119
120    public void SendMessage(string message)
121    {
122        Send(MessageType.Message, message);
123    }
124
125    public T DeserializeFromString<T>(string settings) where T : class
126    {
127        var bytes = Convert.FromBase64String(settings);
128        using (var mstream = new MemoryStream(bytes))
129        {
130            var formatter = new BinaryFormatter();
131            formatter.Binder = new AssemblyBinder();
132            mstream.Seek(0, SeekOrigin.Begin);
133            return formatter.Deserialize(mstream) as T;
134        }
135    }
136
137    public void SendObject(object serializableObject)
138    {
139        using (var mstream = new MemoryStream())
140        {
141            var formatter = new BinaryFormatter();
142            formatter.Serialize(mstream, serializableObject);
143            mstream.Flush();
144            mstream.Position = 0;
145            SendMessage(Convert.ToBase64String(mstream.ToArray()));
146        }
147    }
148
149    private void ParsePacket(string packet)
150    {
151        var parts = packet.Split('\x01');
152
153        var messageType = (MessageType)int.Parse(parts[0]);
154        var senderGuid = new Guid(Convert.FromBase64String(parts[1]));
155        var game = parts[2];
156
157        if (messageType == MessageType.Message && OnMessageReceive != null)
158        {
159            var message = parts[3];
160            OnMessageReceive(senderGuid, message);
161        }
162        else if (messageType == MessageType.Connected && OnConnect != null)
163        {
164            OnConnect(senderGuid);
165        }
166        else if (messageType == MessageType.Disconnected && OnDisconnect != null)
167        {
168            OnDisconnect(senderGuid);
169        }
170    }
171
172    private void ReceiveThread(CancellationToken cancelToken)
173    {
174        var buffer = new StringBuilder();
175
176        while (!cancelToken.IsCancellationRequested)
177        {
178            if (client.Available == 0)
179                continue;
180
181            var receivedBytes = new byte[BLOCK_SIZE];
182            var bytesRead = networkStream.Read(receivedBytes, 0, BLOCK_SIZE);
183
184            for (int i = 0; i < bytesRead; i++)
185            {
186                if (receivedBytes[i] == '\x00')
187                {
188                    ParsePacket(buffer.ToString());
189                    buffer.Clear();
190                }
191                else
192                {
193                    buffer.Append((char)receivedBytes[i]);
194                }
195            }
196        }
197    }
198}
Note: See TracBrowser for help on using the repository browser.