using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Threading; using Serilog; namespace SharpOSC { public class MessageEventArgs : EventArgs { public OscMessage Message { get; set; } } public class TCPClient { public int Port { get { return _port; } } int _port; public string Address { get { return _address; } } public delegate void MessageReceivedHandler(object source, MessageEventArgs args); public event MessageReceivedHandler MessageReceived; private Thread receivingThread; string _address; TcpClient client; public TCPClient(string address, int port) { _port = port; _address = address; } public bool Connect() { try { client = new TcpClient(Address, Port); receivingThread = new Thread(ReceiveLoop); receivingThread.Start(); Log.Debug($"[tcpclient] connected to <{Address}:{Port}>"); return true; } catch (Exception e) { Log.Error(e.Message); return false; } } public void Send(byte[] message) { byte[] slipData = SlipFrame.Encode(message); NetworkStream netStream = client.GetStream(); netStream.Write(slipData.ToArray(), 0, slipData.ToArray().Length); } public void Send(OscPacket packet) { byte[] data = packet.GetBytes(); Send(data); } public bool IsConnected { get { if (client == null) return false; else return client.Connected; } } public void ReceiveLoop() { while (client != null && client.Connected) { Receive(); } //Log.Debug("[tcpclient] - ReceiveLoop has exited"); } public void Receive() { Random random = new Random(); int num = random.Next(1000); try { NetworkStream netStream = client.GetStream(); netStream.ReadTimeout = 250; List responseData = new List(); if (netStream.CanRead) { //var watch = System.Diagnostics.Stopwatch.StartNew(); byte[] buffer = new byte[256]; int bytesRead = 0; int reads = 0; do { bytesRead = netStream.Read(buffer, 0, buffer.Length); responseData.AddRange(buffer); reads += 1; Thread.Sleep(1); //Log.Debug("Thread " + num + ": Bytes read: " + bytesRead + " - " + Encoding.UTF8.GetString(buffer)); } while (netStream.DataAvailable); List messages = SlipFrame.Decode(responseData.ToArray()); foreach (byte[] message in messages) { OscPacket packet = OscPacket.GetPacket(message); OscMessage responseMessage = (OscMessage)packet; //watch.Stop(); //Console.WriteLine($"TCPCLient - message receive took {watch.ElapsedMilliseconds}ms and {reads} reads"); OnMessageReceived(responseMessage); } //Console.WriteLine("Raw TCP In: " + System.Text.Encoding.UTF8.GetString(responseData.ToArray())); } } catch (Exception e) { //Console.WriteLine("TCPSENDER - Receive Exception: " + e.ToString()); } } public void Close() { if (client != null) { if (client.Connected) { Log.Debug($"[tcpClient] closing connection to {Address}"); client.GetStream().Close(); client.Close(); } } } protected virtual void OnMessageReceived(OscMessage msg) { MessageReceived?.Invoke(this, new MessageEventArgs() { Message = msg }); } } }