/// <summary> /// This is generic function which will send UDP command to specific IP, port and return the /// reply if required /// </summary> /// <param name="socket">Socket - must be initialized</param> /// <param name="bytes2Send">Bytes to send to the given socket</param> /// <param name="replyRequired">Is reply required?</param> /// <returns>Reply packet</returns> public async Task <ReplyPacket> SendUdpAsync(UdpClient socket, byte[] bytes2Send, bool replyRequired = true) { ReplyPacket replyPacket = new ReplyPacket(); if (socket is null) { replyPacket.Error = "Socket is null"; return(replyPacket); } if (bytes2Send is null) { replyPacket.Error = "Bytes to send is null"; return(replyPacket); } try { int bytesSent = await socket.SendAsync(bytes2Send, bytes2Send.Length).ConfigureAwait(false); replyPacket.IsSent = true; if (replyRequired) { Task <UdpReceiveResult> taskRecievePacket = socket.ReceiveAsync(); taskRecievePacket.Wait(socket.Client.ReceiveTimeout); if (taskRecievePacket.IsCompleted) { replyPacket.SetReply(taskRecievePacket.Result.Buffer); replyPacket.IsSentAndReplyReceived = true; } } } catch (Exception ex) { replyPacket.Error = ex.Message; } return(replyPacket); }
/// <summary> /// It will connect on the server with given IP and Port then listens on it. Use it in the thread/task /// </summary> /// <param name="ip">Server IP</param> /// <param name="port">Server Port</param> /// <param name="endBytesIdentifier"> /// This identifies the end packet once receive these bytes it will push the packet. If null /// then it pushes as it receives /// </param> /// <param name="connectionTimeoutMs"></param> /// <param name="receiveTimeOut"></param> /// <param name="transmissionTimeout"></param> /// <returns>Connection Status</returns> public bool Connect(string ip, int port, byte[] endBytesIdentifier = null, int connectionTimeoutMs = 2000, int receiveTimeOut = 1000, int transmissionTimeout = 1000) { if (endBytesIdentifier != null) { endBytesIdentifier = endBytesIdentifier.Reverse().ToArray(); } if (IsConnected) { return(IsConnected); } clientTcp = new TcpClient() { ReceiveTimeout = receiveTimeOut, SendTimeout = transmissionTimeout }; try { IAsyncResult result = clientTcp.BeginConnect(ip, port, null, null); bool success = result.AsyncWaitHandle.WaitOne(connectionTimeoutMs, true); IsConnected = clientTcp.Connected; if (!IsConnected) { return(IsConnected); } Port = port; Ip = ip; } catch (Exception ex) { ExceptionHandler?.Invoke(this, ex); return(IsConnected); } try { stream = clientTcp.GetStream(); ReplyPacket replyPacket = new ReplyPacket() { IsSentAndReplyReceived = true, IPSender = ip }; IsConnected = true; List <byte> completePacket = new List <byte>(); Task.Run(async() => { while (clientTcp.Connected) { if (!IsConnected) { break; } if (!stream.DataAvailable) { await Task.Delay(1).ConfigureAwait(false); } else { try { byte[] packet = new byte[clientTcp.Available]; await stream.ReadAsync(packet, 0, packet.Length).ConfigureAwait(false); completePacket.AddRange(packet); int lenth = completePacket.Count; if (endBytesIdentifier != null) { //this will flush any data that was there before connecting to the software //if (lenth > 5000) { completePacket.Clear(); continue; } if (completePacket.Count > endBytesIdentifier.Length) { bool isPacketEndIdentified = false; for (int i = 0; i < endBytesIdentifier.Length; i++) { if (completePacket[lenth - (i + 1)] == endBytesIdentifier[i]) { isPacketEndIdentified = true; } else { isPacketEndIdentified = false; break; } } if (isPacketEndIdentified) { replyPacket.SetReply(completePacket); DataReady?.Invoke(this, replyPacket); completePacket.Clear(); } } } else { replyPacket.SetReply(completePacket); DataReady?.Invoke(this, replyPacket); completePacket.Clear(); } } catch (Exception ex) { ExceptionHandler?.Invoke(this, ex); } } } }); } catch (Exception ex) { ExceptionHandler?.Invoke(this, ex); } return(IsConnected); }
/// <summary> /// Returns the current status of listener /// </summary> /// <returns></returns> public bool StartListener() { if (IsListening) { return(IsListening); } IPAddress serverIP = IPAddress.Parse(Services.CommonUtility.GetIPAddress()); listener = new TcpListener(serverIP, Port); try { listener.Start(); IsListening = true; } catch (Exception ex) { IsListening = false; ExceptionHandler?.Invoke(null, ex); return(IsListening); } Task.Run(async() => { while (IsListening) { try { ReplyPacket replyPacket = new ReplyPacket() { IsSentAndReplyReceived = true }; TcpClient clientTCP = await listener.AcceptTcpClientAsync().ConfigureAwait(false); replyPacket.PortSender = ((IPEndPoint)clientTCP.Client.RemoteEndPoint).Port; replyPacket.IPSender = ((IPEndPoint)clientTCP.Client.RemoteEndPoint).Address.ToString(); if (ReceiveFromThisIPAddressList.Count > 0) { bool isProcessingRequired = false; foreach (var ipAcceptable in ReceiveFromThisIPAddressList) { if (ipAcceptable == replyPacket.IPSender) { isProcessingRequired = true; break; } } if (!isProcessingRequired) { continue; } } int length; NetworkStream stream = clientTCP.GetStream(); List <byte> singlePacket = new List <byte>(); var byteArray = new byte[1024]; while ((length = stream.Read(byteArray, 0, byteArray.Length)) != 0) { var copy = new byte[length]; Array.Copy(byteArray, 0, copy, 0, length); singlePacket.AddRange(copy); } replyPacket.SetReply(singlePacket); DataEvent?.Invoke(this, replyPacket); if (IsAutoReplying) { await stream.WriteAsync(AutoReply?.ToArray(), 0, AutoReply.Count).ConfigureAwait(false); stream.Flush(); } stream.Close(); clientTCP.Close(); } catch (Exception ex) { ExceptionHandler?.Invoke(this, ex); } } listener.Server.Close(); }); return(IsListening); }
/// <summary> /// This is generic function which will send TCP command to specific IP, port and return the /// reply if required /// </summary> /// <param name="inputCommand">Commnad to be sent</param> /// <param name="isReplyRequired">Wait for reply?</param> /// <param name="txTimeout">Transmission timeout (ms)</param> /// <param name="rxTimeout">Receive timeout (ms)</param> /// <param name="connectionTimeout">Connection timeout (ms)</param> /// <param name="fireOnSent">Fires event on packet sent</param> /// <returns>Reply packet</returns> public async Task <ReplyPacket> SendTcpAsync(byte[] inputCommand, bool isReplyRequired = true, int txTimeout = defaultTimeout, int rxTimeout = defaultTimeout, int connectionTimeout = defaultConnectionTimeout, Action <bool> fireOnSent = null) { ReplyPacket replyPacket = new ReplyPacket(); if (inputCommand is null) { replyPacket.Error = "Bytes to send is null"; return(replyPacket); } using (TcpClient client = new TcpClient { ReceiveTimeout = rxTimeout, SendTimeout = txTimeout }) { try { IAsyncResult connectResult = client.BeginConnect(IP, Port, null, null); replyPacket.IPSender = IP; replyPacket.PortSender = Port; Task <bool> connectionTask = new Task <bool>(() => connectResult.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(connectionTimeout))); connectionTask.Start(); if (await connectionTask.ConfigureAwait(false)) { using (NetworkStream stream = client.GetStream()) { await stream.WriteAsync(inputCommand, 0, inputCommand.Length).ConfigureAwait(false); stream.Flush(); replyPacket.IsSent = true; fireOnSent?.Invoke(replyPacket.IsSent); if (isReplyRequired) { //Reading The first byte for the sake of timeout byte[] reply = new byte[1]; await stream.ReadAsync(reply, 0, 1).ConfigureAwait(false); byte[] replyComplete = null; //Reading rest of the bytes if (stream.DataAvailable) { replyComplete = new byte[client.Available + 1]; replyComplete[0] = reply[0]; await stream.ReadAsync(replyComplete, 1, replyComplete.Length - 1).ConfigureAwait(false); } if (replyComplete != null) { replyPacket.SetReply(replyComplete); replyPacket.IsSentAndReplyReceived = true; } else { replyPacket.Error = "Unable to read from remote address"; } } } } else { fireOnSent?.Invoke(replyPacket.IsSent); replyPacket.Error = "Connection TimeOut/Server Not Found"; } } catch (Exception ex) { replyPacket.Error = ex.Message; } } return(replyPacket); }