Lost frames on synchrous/asynchrous data receiveing - c#

I have some problem with receiving frames in C#. After few hours from application start, some frames are lost.
Well, at start I'm running two threads which are receiving data. Code:
public void ATSListenerThreadA(MainWindow mainWindow)
{
UdpClient listenerA = new UdpClient(19001);
listenerA.Client.ReceiveBufferSize = 1000;
IPEndPoint remoteIPEndPointA = new IPEndPoint(IPAddress.Any, 1);
Byte[] receivedBytes;
try
{
while (mainWindow.ATSThreadActive)
{
receivedBytes = listenerA.Receive(ref remoteIPEndPointA);
if (receivedBytes.Length > 170)
{
Log.Write(MessageType.Info, "BUG KANAL A: " + BitConverter.ToString(receivedBytes));
}
mainWindow.ATSTimeoutTimer.Start();
ATSDataReceived(Channel.A, mainWindow, receivedBytes);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public void ATSListenerThreadB(MainWindow mainWindow)
{
UdpClient listenerB = new UdpClient(19002);
listenerB.Client.ReceiveBufferSize = 1000;
IPEndPoint remoteIPEndPointB = new IPEndPoint(IPAddress.Any, 1);
Byte[] receivedBytes;
try
{
while (mainWindow.ATSThreadActive)
{
receivedBytes = listenerB.Receive(ref remoteIPEndPointB);
if (receivedBytes.Length > 170)
{
Log.Write(MessageType.Info, "BUG KANAL B: " + BitConverter.ToString(receivedBytes));
}
mainWindow.ATSTimeoutTimer.Start();
ATSDataReceived(Channel.B, mainWindow, receivedBytes);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ATSDataReceived(Channel channel, MainWindow mainWindow, Byte[] received)
{
try
{
mainWindow.Dispatcher.Invoke(() =>
{
mainWindow.ATSStatusLabel.Foreground = System.Windows.Media.Brushes.Green;
mainWindow.ATSStatusLabel.Content = "OK";
});
ATSInterface.UpdateObjects(channel, received);
}
catch (Exception ex)
{
mainWindow.Dispatcher.Invoke(() =>
{
mainWindow.ATSStatusLabel.Foreground = System.Windows.Media.Brushes.Red;
mainWindow.ATSStatusLabel.Content = "ERR";
});
Log.Write(MessageType.Warning, ex.Message);
}
lock (this)
{
if (mainWindow.ATSTimeoutTimer != null)
{
mainWindow.ATSTimeoutTimer.Stop();
mainWindow.ATSTimeoutTimer.Start();
}
}
}
Then, in ATSDataReceived method, received data are processed with calling method ATSInterface.UpdateObjects(). Of course inside ATSInterface.UpdateObjects() method is lock. I was trying to receiving data synchronously and asynchronously, but it doesn't change anything. Also I was checking if two frames are not sticking together, but it's not this too. As I said, problem araises after few hours from program start, in both threads simultaneously.
I might add that frames are coming very often, once at ~150 ms.
What can be a reason?

some frames are lost.
That's perfectly normal for UDP. By design, you may or may not ever receive a datagram that was sent to you.
Other unreliable behaviors of UDP include the possibility that a given datagram may be received more than once, and that one datagram may be received after a different datagram that was sent later than it (i.e. the datagrams are not guaranteed to be received in the same order in which they were sent).
If you want reliable communications, you will need to use TCP, or add reliability features on top of your UDP protocol.

udp is unreliable protocol to use.
if you want to make sure that everything arrives you need to use TcpClient instead.

Related

udpclient.receive() suddenly stops receiving

I'm using UdpClient to receive data from a single host(actually it's a microcontroller that sends 32 bytes of data every 4 milliseconds.
The program I wrote is pretty simple.
I'm initializing the UdpClient like this(in Program.cs):
public static UdpClient client = new UdpClient(1414);
after that i do this in Form_Load event:
static UdpClient client = Program.client;
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
and then call the client.Recieve() like this:
Task.Run(() =>
{
while (true)
{
try
{
data = client.Receive(ref RemoteIpEndPoint);
}
catch (Exception ex)
{
String err_type = ex.GetType().Name;
if (err_type == "SocketException")
{
MessageBox.Show("Cannot Find The Device.", "Device Error.");
}
}
}
});
the program runs fine on my own system (using Windows 10). However when i run this program on windows 7,at random times,but with 100% chance client.Recieve() stops working and the program no longer receives any data. no exception is thrown. to find the root of the problem, I installed Wireshark to test if there is any incoming data.The answer was no(the LAN port light stops blinking too) . What has me confused is that this does not happen on windows 10.
The thing is, you miss all exceptions except SocketException.
To find out, what's going on, please, rewrite your catch block:
Task.Run(() =>
{
while (true)
{
try
{
data = client.Receive(ref RemoteIpEndPoint);
}
catch (SocketException ex)
{
MessageBox.Show("Cannot Find The Device.", "Device Error.");
}
catch (Exception e)
{
MessageBox.Show(e.GetType().Name, e.Message);
}
}
});
Turns out my code was completely fine.
This was a hardware problem on our side.

Socket on a Thread stops processing and locks the UI

I have a standalone test application developed in c# (4.5).
The application is primarily meant for sending some data to COM ports. The application accepts the data through the UI and the corresponding data is sent to respective COM ports.
For eg: Data from text box 1 goes to COM 1 on pressing a button, Data from Textbox 2 goes to COM 2 on pressing a different button etc.
Later I had to add a functionailty where a different set of data has to be accepted via Windows sockets and has to be sent to a different COM port other than above. This listening socket could receive data from multiple sources. If the listening socket receives back to back socket data, the application is expected to queue the data and process the data on a First come first serve bases.
Hence I created a synchronous socket to receive data. If the server receives data from 2 sources, it processes the data from source 1 and sends the completion status to source 1 and then takes the data from source 2,processes it and informs the status and this goes on. The socket is created on a thread so that it could receive and process data independently from the UI.
The application was meeting its objective as most of the communication was through sockets and people were not really using the UI for entering data.
Recently, as people started UI, i noticed a completely new issue. When someone tries to enters a data on to UI while the socket data is in process, it stops the socket data processing. When I press ctrl+Alt+Del on the host, it resumes the processing of the socket data.
I could not identify my mistake here. Also, I looked over to the Backgroundworkder class but I am not sure if that would allow the sockets commands to be processed in a synchronous way.
Please treat me as a newbie as I am still learning and complex suggestions might be hard to digest.
public partial class frm_bot : Form
{
public frm_bot()
{
StartServer();
}
private void frm_bot_Load(object sender, EventArgs e)
{
try
{
myThread = new System.Threading.Thread(new System.Threading.ThreadStart(OnClientConnect));
myThread.IsBackground = true;
myThread.Start();
}
catch (Exception ex)
{
showErrorMsg(ex.Message);
}//catch
}
public void StartServer()
{
InitializeComponent();
System.Net.IPAddress localIPAddress = System.Net.IPAddress.Parse(GetlocalIp());
IPEndPoint ipLocal = new IPEndPoint(localIPAddress, 8089);
_listener = new TcpListener(ipLocal);
}
private void OnClientConnect()
{
try
{
_listener.Start();
TcpClient clientSocket = default(TcpClient);
clientSocket = _listener.AcceptTcpClient();
_clientSocket = clientSocket;
ReadCallback();
}
catch (Exception se)
{
MessageBox.Show("Could not bind to Port 8089! Please close all Applications that uses Port 8089");
}
}
public void ReadCallback()
{
try
{
using (StreamReader sr = new StreamReader(_clientSocket.GetStream()))
using (StreamWriter sw = new StreamWriter(_clientSocket.GetStream()))
{
sw.AutoFlush = true;
char[] c = null;
while (sr.Peek() >= 0)
{
c = new char[25];
sr.Read(c, 0, c.Length);
Console.WriteLine(c);
}
string d = new string(c);
string[] cmddata = d.Split('\0');
string dataFromClient = cmddata[0];
if (dataFromClient.Length == 0)
{
Console.WriteLine("Client sent empty string!");
}
else
{
ProcessSocketData(dataFromClient);
sw.Write("Done");
}
sw.Close();
}
OnClientConnect();
}
catch (Exception ex)
{
OnClientConnect();
return;
}
}
public void ProcessSocketData(string sockdata)
{
try
{
// Socket data is processed here.
}
catch (Exception ex)
{
MessageBox.Show("Exception on ProcessSocketData: " + ex.Message);
return;
}
}
}

Cause of high UDP package loss on localhost?

In my WPF 4.0 application, I have a UDP listener implemented as shown below. On my Windows 7 PC, I'm running both server and client on localhost.
Each received datagram is a scanline of a larger bitmap, so after all scanlines have been received the bitmap is shown on the UI thread. This seems to work. However, occasionally some 1-50% scanlines are missing. I would expect this on a weak network connection, but not when run locally.
What may cause UDP package loss with the following piece of code?
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, PORT);
udpClient = new UdpClient(endPoint);
udpClient.Client.ReceiveBufferSize = 65535; // I've tried many different sizes...
var status = new UdpStatus()
{
u = udpClient,
e = endPoint
};
udpClient.BeginReceive(new AsyncCallback(UdpCallback), status);
private void UdpCallback(IAsyncResult ar)
{
IPEndPoint endPoint = ((UdpStatus)(ar.AsyncState)).e;
UdpClient client = ((UdpStatus)(ar.AsyncState)).u;
byte[] datagram = client.EndReceive(ar, ref endPoint);
// Immediately begin listening for next packet so as to not miss any.
client.BeginReceive(new AsyncCallback(UdpCallback), ar.AsyncState);
lock (bufferLock)
{
// Fast processing of datagram.
// This merely involves copying the datagram (scanline) into a larger buffer.
//
// WHEN READY:
// Here I can see that scanlines are missing in my larger buffer.
}
}
If I put a System.Diagnostics.Debug.WriteLine in my callback, the package loss increases dramatically. It seems that a small millisecond delay inside this callback causes problems. Still, the same problem is seen in my release build.
UPDATE
The error becomes more frequent when I stress the UI a bit. Is the UdpClient instance executed on the main thread?
To avoid the thread block issue, try this approach that uses the newer IO Completion port receive method:
private void OnReceive(object sender, SocketAsyncEventArgs e)
{
TOP:
if (e != null)
{
int length = e.BytesTransferred;
if (length > 0)
{
FireBytesReceivedFrom(Datagram, length, (IPEndPoint)e.RemoteEndPoint);
}
e.Dispose(); // could possibly reuse the args?
}
Socket s = Socket;
if (s != null && RemoteEndPoint != null)
{
e = new SocketAsyncEventArgs();
try
{
e.RemoteEndPoint = RemoteEndPoint;
e.SetBuffer(Datagram, 0, Datagram.Length); // don't allocate a new buffer every time
e.Completed += OnReceive;
// this uses the fast IO completion port stuff made available in .NET 3.5; it's supposedly better than the socket selector or the old Begin/End methods
if (!s.ReceiveFromAsync(e)) // returns synchronously if data is already there
goto TOP; // using GOTO to avoid overflowing the stack
}
catch (ObjectDisposedException)
{
// this is expected after a disconnect
e.Dispose();
Logger.Info("UDP Client Receive was disconnected.");
}
catch (Exception ex)
{
Logger.Error("Unexpected UDP Client Receive disconnect.", ex);
}
}
}

Delay when send string via socket

I make an application in android can send character code to server C# when user input on android keyboard.
This is send method in android side:
public Boolean writeMessage(String message) {
try {
printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.println(message);
return true;
} catch (Exception ex) {
Log.e(TAG,"write error: " +ex.getMessage());
return false;
}
}
And server listen the messages (C#):
Thread myThread = new Thread(new ThreadStart(ServeClient));
myThread.Start();
void ServeClient(){
StreamReader reader = new StreamReader(tcpClient.GetStream());
while (true)
{
try
{
String message = reader.ReadLine();
if (message != null)
{
Console.WriteLine(message);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
My code works, but when user input faster, the server delay read message in 1,2 or 3 seconds (I have test the method get character when user input, it works fine, not delay). Where is my problem? Thanks in advance!
Your problem may be caused by Nagle's algorithm reducing TCP traffic. Consider setting TCP_NODELAY on your client (and server - TcpClient.Client.NoDelay - if communication is two-way).
Edit: For java it is Socket.setTcpNoDelay method.

How to connect to modems with tcp clients, in multiple port or other way?

I have around 5000 modem (thin clients), and I want to communicate with them, one of a my method is like this : string GetModemData(modemID), now I have an open port in server that listens to modem and I'm using socket programming to send data to modems (calling related function), but when i want send data to multiple modem in a same time and get response from them, I don't know what should i do? I can send data to one modem and waiting for its response and then send another data to other modems (sequential), but the problem is client should be wait long time to get answer(may be some different client want to get some information from modems so they all will be wait into the Q or something like this), I think one way to solving this problem is to use multiple port and listen for each modem to related port, but it takes too many ports and also may be memory usage going up and exceed my available memory space, so some lost may be occurred (is this true?). what should to do ? I'd thinking about Parallelism, but i think its not related i should to wait for one port, because i don't know should to pass current received data to which client. I'm using asp.net.
currently I'm doing like this:
private void StartListener()
{
ModemTcpListener = new TcpListener(ModemPort);
//ClientTcpListener = new TcpListener(ClientPort);
ModemTcpListener.Start();
ModemTcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptModemCallback), ModemTcpListener);
}
and in return
private void DoReadModemCallback(IAsyncResult ar)
{
try
{
bool bRet = ar.AsyncWaitHandle.WaitOne(420000);
Modem modem = ar.AsyncState as Modem;
if (!bRet || modem == null)
{
return;
}
}
catch{}
// now send data to which client?????? if i'm going to use async????
}
and :
private void DoAcceptModemCallback(IAsyncResult ar)
{
try
{
ModemTcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptModemCallback), ModemTcpListener);
TcpClient tcpClient = ModemTcpListener.EndAcceptTcpClient(ar);
Modem modem= new Modem(tcpClient, "");
tcpClient.GetStream().BeginRead(modem.Buffer, 0, tcpClient.ReceiveBufferSize, new AsyncCallback(DoReadModemCallback), modem);
ModemTcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptModemCallback), ModemTcpListener);
Log.Write("a Modem connect ...");
}
catch (Exception ex)
{
}
}
Heres an example keeping track of all your clients. I've compacted it for readability. You should really split it up into multiple classes.
I'm using Pool (which I just created and commited) and SimpleServer. Both classes are part of a library that I'm currently building (but far from done).
Don't be afraid of having 5000 sockets open, they do not consume much resources when you are using asynchronous operations.
public class SuperServer
{
private List<ClientContext> _clients = new List<ClientContext>();
private SimpleServer _server;
private Pool<byte[]> _bufferPool;
public SuperServer()
{
// Create a buffer pool to be able to reuse buffers
// since your clients will most likely connect and disconnect
// often.
//
// The pool takes a anonymous function which should return a new buffer.
_bufferPool = new Pool<byte[]>(() => new byte[65535]);
}
public void Start(IPEndPoint listenAddress)
{
_server = new SimpleServer(listenAddress, OnAcceptedSocket);
// Allow five connections to be queued (to be accepted)
_server.Start(5);
}
// you should handle exceptions for the BeginSend
// and remove the client accordingly.
public void SendToAll(byte[] info)
{
lock (_clients)
{
foreach (var client in _clients)
client.Socket.BeginSend(info, 0, info.Length, SocketFlags.None, null, null);
}
}
// Server have accepted a new client.
private void OnAcceptedSocket(Socket socket)
{
var context = new ClientContext();
context.Inbuffer = _bufferPool.Dequeue();
context.Socket = socket;
lock (_clients)
_clients.Add(context);
// this method will eat very few resources and
// there should be no problem having 5000 waiting sockets.
context.Socket.BeginReceive(context.Inbuffer, 0, context.Inbuffer.Length, SocketFlags.None, OnRead,
context);
}
//Woho! You have received data from one of the clients.
private void OnRead(IAsyncResult ar)
{
var context = (ClientContext) ar.AsyncState;
try
{
var bytesRead = context.Socket.EndReceive(ar);
if (bytesRead == 0)
{
HandleClientDisconnection(context);
return;
}
// process context.Inbuffer here.
}
catch (Exception err)
{
//log exception here.
HandleClientDisconnection(context);
return;
}
// use a new try/catch to make sure that we start
// read again event if processing of last bytes failed.
try
{
context.Socket.BeginReceive(context.Inbuffer, 0, context.Inbuffer.Length, SocketFlags.None, OnRead,
context);
}
catch (Exception err)
{
//log exception here.
HandleClientDisconnection(context);
}
}
// A client have disconnected.
private void HandleClientDisconnection(ClientContext context)
{
_bufferPool.Enqueue(context.Inbuffer);
try
{
context.Socket.Close();
lock (_clients)
_clients.Remove(context);
}
catch(Exception err)
{
//log exception
}
}
// One of your modems
// add your own state info.
private class ClientContext
{
public byte[] Inbuffer;
public Socket Socket;
}
}
Used classes:
Pool: http://fadd.codeplex.com/SourceControl/changeset/view/58858#1054902
SimpleServer: http://fadd.codeplex.com/SourceControl/changeset/view/58859#1054893
You need to use the asynchronous tcp/ip methods. This article shows how:
http://www.codeproject.com/KB/IP/asyncsockets.aspx
The critical piece is the BeginReceive() and related callback functions. Any more q's, please leave comments to this answer ;) BEST OF LUCK!
You need multi threading, whenever a client establishes a connection to the server start a new thread for it and start communication send/receive.
Here are some articles explaining multithreading in c#,
c-sharpcorner
codeproject
And here's a sample server application with multithreading,
http://www.dotnetspider.com/resources/2829-A-multi-readed-server-C-which-finds-prime-num.aspx

Categories

Resources