Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Net;
- using System.Net.Sockets;
- using Newtonsoft.Json;
- using TcpJsonLib.EventHandlers;
- namespace TcpJsonLib
- {
- public class JsonClient : IDisposable
- {
- /// <summary>
- /// Sets whether or not the client should automatically attempt to reconnect after a specified amount of ms (see <see cref="AutoReconnectDelay"/>).
- /// </summary>
- public bool AutoReconnect { get; set; }
- /// <summary>
- /// The amount of miliseconds to wait before attempting to reconnect. (if <see cref="AutoReconnect"/> is set to true).
- /// </summary>
- public int AutoReconnectDelay { get; set; } = 1000;
- private Socket client;
- public Socket Client
- {
- get { return client; }
- private set
- {
- client = value;
- if (client.Connected)
- BeginReceive();
- }
- }
- public delegate void ClientConnectedEventHandler(ClientConnectedEventArgs e);
- public event ClientConnectedEventHandler ClientConnected;
- public delegate void ClientDisconnectedEventHandler(ClientDisconnectedEventArgs e);
- public event ClientDisconnectedEventHandler ClientDisonnected;
- private byte[] buffer;
- const int BUFFER_SIZE = 1024;
- private byte[] lenBuffer;
- const int LEN_BUFFER_SIZE = 4;
- public bool Connected => Client?.Connected ?? false;
- private MemoryStream ms;
- private Dictionary<string, Action<JsonClient, dynamic>> OnReceiveActions;
- public JsonClient()
- {
- buffer = new byte[BUFFER_SIZE];
- lenBuffer = new byte[LEN_BUFFER_SIZE];
- OnReceiveActions = new Dictionary<string, Action<JsonClient, dynamic>>();
- client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- }
- public JsonClient(IPAddress address, int port) : this()
- {
- Connect(address, port);
- }
- public static implicit operator JsonClient(TcpClient client)
- {
- return new JsonClient { Client = client.Client };
- }
- /// <summary>
- /// Sends a packet to the remote host.
- /// </summary>
- /// <param name="key"></param>
- /// <param name="json"></param>
- public void Emit(string key, dynamic json)
- {
- using (MemoryStream ms = new MemoryStream())
- {
- ms.Position = 4L;
- using (BinaryWriter bw = new BinaryWriter(ms))
- {
- bw.Write(key);
- string jsonStr = JsonConvert.SerializeObject(json);
- bw.Write(jsonStr);
- ms.Position = 0L;
- bw.Write((int)ms.Length);
- }
- byte[] data = ms.ToArray();
- Client.BeginSend(data, 0, data.Length, SocketFlags.None, WriteCallback, null);
- }
- }
- private void WriteCallback(IAsyncResult ar)
- {
- try { Client.EndSend(ar); }
- catch { }
- }
- /// <summary>
- /// Establishes a connection with the remote host.
- /// </summary>
- /// <param name="address"></param>
- /// <param name="port"></param>
- public void Connect(IPAddress address, int port)
- {
- Client.BeginConnect(new IPEndPoint(address, port), ConnectCallback, null);
- }
- /// <summary>
- /// Adds a listener for incoming packets, and invokes the action with the packet data.
- /// </summary>
- /// <param name="key"></param>
- /// <param name="action"></param>
- public void AddListener(string key, Action<JsonClient, dynamic> action)
- {
- if (OnReceiveActions.ContainsKey(key))
- throw new Exception("A listener with this key is already present.");
- OnReceiveActions.Add(key, action);
- }
- /// <summary>
- /// Remove a listener for incoming packets.
- /// </summary>
- /// <param name="key"></param>
- public void RemoveListener(string key)
- {
- if (!OnReceiveActions.ContainsKey(key))
- throw new Exception("No existing listener with this key could be found.");
- OnReceiveActions.Remove(key);
- }
- private void ConnectCallback(IAsyncResult ar)
- {
- try
- {
- Client.EndConnect(ar);
- ClientConnected?.Invoke(new ClientConnectedEventArgs(this, client.RemoteEndPoint));
- BeginReceive();
- }
- catch (SocketException ex)
- {
- throw ex;
- }
- }
- private void ReceiveCallback(IAsyncResult ar)
- {
- try
- {
- int len = Client.EndReceive(ar);
- if (len <= 0)
- {
- Close();
- return;
- }
- int toReceive = BitConverter.ToInt32(lenBuffer, 0);
- ms = new MemoryStream();
- Client.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceivePacketCallback, toReceive - LEN_BUFFER_SIZE);
- }
- catch { Close(); }
- }
- private void ReceivePacketCallback(IAsyncResult ar)
- {
- try
- {
- int len = Client.EndReceive(ar);
- int toReceive = (int)ar.AsyncState - len;
- ms.Write(buffer, 0, len);
- if (toReceive > 0)
- {
- Client.BeginReceive(buffer, 0, Math.Min(BUFFER_SIZE, toReceive), SocketFlags.None, ReceivePacketCallback, toReceive);
- return;
- }
- ms.Position = 0L;
- using (BinaryReader br = new BinaryReader(ms))
- {
- string key = br.ReadString();
- string dataStr = br.ReadString();
- dynamic data = JsonConvert.DeserializeObject(dataStr);
- if (OnReceiveActions.ContainsKey(key))
- OnReceiveActions[key].Invoke(this, data);
- }
- ms.Close();
- }
- catch (SocketException) { Close(); }
- catch { }
- finally { BeginReceive(); }
- }
- private void BeginReceive()
- {
- try
- {
- Client.BeginReceive(lenBuffer, 0, LEN_BUFFER_SIZE, SocketFlags.None, ReceiveCallback, null);
- }
- catch { }
- }
- /// <summary>
- /// Close the connection with a remote host.
- /// </summary>
- public void Close()
- {
- if (client != null)
- {
- client?.Close();
- ClientDisonnected?.Invoke(new ClientDisconnectedEventArgs(this));
- }
- }
- public void Dispose()
- {
- client?.Close();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement