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

Revision 7155, 5.4 KB checked in by sieerinn, 6 years ago (diff)

Koodin siistimistä.

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