I am reading from an Arduino, which is sending text through the USB port. The Arduino sends the status of it's outputs every second. On the command received event I set a couple of checkboxes (either shutter open or mains on, or lights on) and also it outputs the data it received to a multiline text box.
Anyway.... it all works, for a few seconds, then slows down and eventually after about 10 minutes I get a Out of Memory exception. I cant figure out whats going wrong, I assume its in the class that reads the serial data - so here is that code, can anybody see anything wrong?
using System;
using System.IO.Ports;
namespace WOCA.Core.SerialComms
{
internal class ArduinoCommunicator : ICommunicator
{
public event EventHandler<CommsEventsArg> CommandReceived;
internal ArduinoCommunicator(string comPort)
{
Port = new SerialPort(comPort) {BaudRate = 9600, DtrEnable = true};
Port.DataReceived += PortOnDataReceived;
}
private SerialPort Port { get; set; }
public bool IsOpen { get; set; }
public void Open()
{
try
{
if (!Port.IsOpen)
{
Port.Open();
IsOpen = true;
}
else
{
throw new InvalidSerialCommsException("Serial port already open");
}
}
catch (Exception ex)
{
throw new InvalidSerialCommsException("Serial Port error: " + ex.Message);
}
}
public void Close()
{
try
{
if (Port.IsOpen)
{
Port.Close();
IsOpen = false;
}
else
{
throw new InvalidSerialCommsException("Serial port not open");
}
}
catch (Exception)
{
throw new InvalidSerialCommsException("Serial port error");
}
}
public void SendCommand(string command)
{
try
{
if (Port.IsOpen)
{
Port.Write(command);
}
else
{
throw new InvalidSerialCommsException("Serial port not open");
}
}
catch (Exception)
{
throw new InvalidSerialCommsException("Serial port error, the command has not been sent");
}
}
private void PortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
SerialPort serialPort = sender as SerialPort;
if (serialPort != null)
{
string command = serialPort.ReadLine();
command = command.Remove(command.Length-1,1);
CommsEventsArg args = new CommsEventsArg(command);
OnCommandReceived(args);
}
}
protected virtual void OnCommandReceived(CommsEventsArg e)
{
EventHandler<CommsEventsArg> handler = CommandReceived;
if (handler != null)
{
handler(this, e);
}
}
}
}
This may be caused by the implementation of the class SerialPort. It may never never gives to control to other threads so the finalization thread cannot finalize the objects and free the memory. See my article about it: http://alexatnet.com/articles/net-memory-management-and-garbage-collector#best-practices
To fix it you need to add
Thread.CurrentThread.Join(100)
For example, it may be added to PortOnDataReceived. This will allow finalization thread to run pending finalizers.
Related
I am building a tcp port forwarding application. The client connects to the server on a particular port and internally the request is routed in the server to a remote port and response is passed back to the client. Below is my code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace BBGRouter
{
class Router
{
#region log4net
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#endregion //log4net
bool isShutdown = false;
private Socket router = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public event EventHandler OnRestartNeeded;
//only one time
Thread thRouterTh;
public Router()
{
thRouterTh = new Thread(new ParameterizedThreadStart(RouterProc));
}
IPEndPoint local, remote;
public void Start(IPEndPoint local, IPEndPoint remote)
{
if (log.IsInfoEnabled) { log.Info("Listening on " + local); }
this.local = local;
this.remote = remote;
router.Bind(local);
router.Listen(10);
thRouterTh.Name = "router thread";
thRouterTh.Start();
}
void RouterProc(object obj)
{
while (!isShutdown)
{
try
{
var source = router.Accept();
if (log.IsInfoEnabled) { log.Info("Creating new session...."); }
var destination = new Router();
var state = new State(source, destination.router);
destination.Connect(remote, source);
source.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, OnDataReceive, state);
}
catch (Exception ex)
{
if (log.IsErrorEnabled) { log.Error("Exception in Router thread", ex); }
if (isShutdown) { if (log.IsInfoEnabled) { log.Info("Shutting down..."); } }
}
}
}
public void Join()
{
if (thRouterTh != null)
thRouterTh.Join();
}
private void StopAndFireRestart(EventArgs e)
{
Stop();
log.Info("Stopped router");
EventHandler handler = OnRestartNeeded;
if (handler != null)
{
log.Info("Firing the restart event now");
handler(this, e);
}
}
public void Stop()
{
try
{
isShutdown = true;
if (log.IsInfoEnabled) { log.Info("Stopping router thread"); }
router.Shutdown(SocketShutdown.Both);
//router.Shutdown(SocketShutdown.Receive);
}
catch (Exception ex)
{
if (log.IsErrorEnabled) { log.Error("Exception while stopping", ex); }
}
finally
{
thRouterTh.Interrupt();
router.Dispose();
}
}
private void Connect(EndPoint remoteEndpoint, Socket destination)
{
if (log.IsInfoEnabled) { log.InfoFormat("connecting session at {0}", remoteEndpoint.ToString()); }
var state = new State(router, destination);
try
{
router.Connect(remoteEndpoint);
router.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, OnDataReceive, state);
}
catch (SocketException e)
{
if (log.IsErrorEnabled) { log.Error(string.Format("SocketException while connect: Exception: {0}, ErrorCode: {1}", e, e.ErrorCode)); }
// Stop the service
StopAndFireRestart(new EventArgs());
}
catch (Exception ex)
{
if (log.IsErrorEnabled) { log.Error("exception while connect {0}", ex); }
}
}
private void OnDataReceive(IAsyncResult result)
{
var state = (State)result.AsyncState;
try
{
var bytesRead = state.SourceSocket.EndReceive(result);
if (bytesRead > 0)
{
log.Info(string.Format("Bytes read: {0}", bytesRead));
state.DestinationSocket.Send(state.Buffer, bytesRead, SocketFlags.None);
state.SourceSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, OnDataReceive, state);
}
}
catch (Exception e)
{
if (log.IsErrorEnabled) { log.Error("Exception receiving the data, Closing source/destination sockets", e); }
//state.DestinationSocket.Close();
//state.SourceSocket.Close();
//StopAndFireRestart(new EventArgs());
}
}
private class State
{
public Socket SourceSocket { get; private set; }
public Socket DestinationSocket { get; private set; }
public byte[] Buffer { get; private set; }
public State(Socket source, Socket destination)
{
SourceSocket = source;
DestinationSocket = destination;
Buffer = new byte[8192];
}
}
}
}
The problem happens when suddenly the client gets disconnected from the remote port randomly after 4-5 hrs. How can I reconnect the client gracefully so that there is no change in the client code ?
Why don't you solve this issue with netsh?
netsh interface portproxy add v4tov4 listenport=LOCALPORT listenaddress=localhost connectport=REMOTEPORT connectaddress=REMOTEADDRESS
or
netsh interface portproxy add v4tov4 listenport=LOCALPORT connectport=REMOTEPORT connectaddress=REMOTEADDRESS
More information on netsh available on MSDN.
I have a simple application which sends and receives data.
ZSocketExample client = new ZSocketExample("127.0.0.1:5555");
client.send("test");
This is my client class:
public class ZSocketExample:IDisposable
{
public delegate void ReceiveEventHandler(object sender, SocketEventArgs e);
public event ReceiveEventHandler ReceiveEvent;
private ZmqContext zmqContext;
private ZmqSocket zmqSocket;
private string host;
private bool isRunning;
private bool disposed = false;
public ZSocketExample(string host)
{
try
{
zmqContext = ZmqContext.Create();
zmqSocket = zmqContext.CreateSocket(SocketType.DEALER);
ZHelpers.SetID(zmqSocket, Encoding.UTF8);
zmqSocket.Connect(host);
this.isRunning = true;
zmqSocket.ReceiveReady += new EventHandler<SocketEventArgs>(zmqSocket_ReceiveReady);
zmqSocket.SendReady += new EventHandler<SocketEventArgs>(zmqSocket_SendReady);
Poller poller = new Poller(new List<ZmqSocket> { zmqSocket });
while (isRunning)
{
poller.Poll(TimeSpan.FromSeconds(5));
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
void zmqSocket_ReceiveReady(object sender, SocketEventArgs e)
{
Console.WriteLine("Receive Ready");
}
void zmqSocket_SendReady(object sender, SocketEventArgs e)
{
Console.WriteLine("Send Ready");
}
public void send(string msg)
{
zmqSocket.Send(msg, Encoding.UTF8);
if (ReceiveEvent != null)
ReceiveEvent(this, null);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
close();
}
disposed = true;
}
public void close()
{
isRunning = false;
zmqSocket.Linger = TimeSpan.FromSeconds(1);
zmqSocket.Close();
zmqContext.Terminate();
}
}
But somehow it doesnot send or receive. Can someone tell me what do I do wrong? And this example blocks the main application. how can I make it non blocking?
ZeroMQ socket is not thread safe, you can't use it from multiple threads without using some kind of synchronization.
In your example you call the close which set a variable and then immediately close the socket, this is wrong, you should close the socket when you are out of the while loop.
Regarding receive/send ready, you rarely need to register for send ready, send ready will let you know when you can send a message, in the dealer socket if you are connected you always will be ready to send (unless the highwater has reached).
Receive Ready will be invoked when there is message ready to be received, if other side send you a message the receive ready will be invoked.
For the last part, blocking, you need a dedicate thread to handle zeromq sockets, you can have one thread that handle multiple sockets using the poller.
So i know there are a lot of articles out there on this topic and i did read a lot of them i would say but for some reason im sure my code is not doing what it is supposed to do.
I want to close a connection between my Server and my Client.
Now on the serverside i start the disconnect with this code
public void shutdown()
{
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
And on the Client side i have some troubles understanding how i get to the disconnect what i believe is happening is the following: in my async receive callback i should get an error since the server started a shutdown sequence and i have to handle that (right???) so my code for the client looks like this:
ReceiveCallback:
private void ReceiveCallback(IAsyncResult result)
{
int bytesRecieved = 0;
byte[] tempBuff;
//Try to receive But if a Socket error occures disconnect otherwise start Receiving again
try
{
bytesRecieved = _socket.EndReceive(result);
}
catch (SocketException sockEx)
{
Disconnect(sockEx);
return;
}
catch (ObjectDisposedException disposeEx)
{
Disconnect(disposeEx);
return;
}
catch (Exception ex)
{
StartReceive();
return;
}
if (bytesRecieved == 0)
{
StartReceive();
return;
}
tempBuff = new byte[bytesRecieved];
Buffer.BlockCopy(_buffer, 0, tempBuff, 0, bytesRecieved);
StartReceive();
_packHandler.handlePacket(tempBuff);
}
Disconnect:
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
_socket.BeginDisconnect(false, DisconnectCallback, null);
}
DisconnectCallback
private void DisconnectCallback(IAsyncResult result)
{
_socket.EndDisconnect(result);
_socket.Close();
}
(The Disconnect Method is overloaded so if i get an exception it puts up a messageBox and then also calls Disconnect. Just so i know what happened.)
Where am i wrong and what can i improve uppon ???
I tried the code and it seemed to work but i then looked with netstat if all sockets are closed and the client socket was not. It was in FIN_WAIT_2 which means that it (or the server???) did not yet send the FIN packet right ?
Oh and then i tried it again with this line changed:
if (bytesRecieved == 0)
{
StartReceive();
return;
}
TO
if (bytesRecieved == 0)
{
Disconnect;
return;
}
which then threw an exception on the serverside and on the clientside the client said that the connection was closed by the server ???
EDIT: Even when i have closed both Programs Netstat still shows the port in a WAITING status. what does that tell me ?
Your normal disconnect has a shutdown which will clear the socket so it can disconnect properly but your async style never calls shutdown. I added it in a convenient location below.
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
_socket.Shutdown(SocketShutdown.Both); // Make sure to do this
_socket.BeginDisconnect(false, DisconnectCallback, null);
}
EDIT:
From the sounds of it you don't have a reason to be using the Async Method? The async methods are so you can send data in a separate execution thread freeing up your thread to do some data processing for instance while that occurs.
I don't see any processing going on so I suggest you change disconnect like this and see if it resolves the problem. Because I don't think you are waiting on the Async methods which will not work out well.
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
shutdown(); //Your standard disconnect that you showed up top. Scoping might be required.
}
A bit of data on Async can be scrounged up here: http://msdn.microsoft.com/en-us/library/38dxf7kt(v=vs.110).aspx
Important is:
If a server starts a shutdown sequence you DO have to handle it
Both sides have to call shutdown on their socket
You need a way to notice the disconnect (it does not give you an error, or least it didnt for me)
Therefor I created my own class customSocket which inherits from Socket
public class customSocket : Socket
{
#region Properties
private readonly Timer _timer;
private const int _interval = 1000;
private bool Connected
{
get
{
bool part1 = Poll(1000, SelectMode.SelectRead);
bool part2 = (Available == 0);
if (part1 && part2)
return false;
else
return true;
}
}
public bool EventsEnabled
{
set
{
if (value)
{
_timer.Start();
}
else
_timer.Stop();
}
}
#endregion
#region Constructors
public customSocket(AddressFamily addressFamily, SocketType sockType, ProtocolType protocolType)
: base(addressFamily, sockType, protocolType)
{
_timer = new Timer { Interval = _interval };
_timer.Elapsed += TimerTick;
}
public customSocket(SocketInformation sockInfo)
: base(sockInfo)
{
_timer = new Timer { Interval = _interval };
_timer.Elapsed += TimerTick;
}
#endregion
#region Events
public event EventHandler<EventArgs> Socket_disconected;
public void Raise_Socket_disconnected()
{
EventHandler<EventArgs> handler = Socket_disconected;
if (handler != null)
{
handler(this,new EventArgs());
}
}
private void TimerTick(object sender, EventArgs e)
{
if (!Connected)
{
Raise_Socket_disconnected();
}
}
#endregion
}
This version of a socket has an Event for a disconnect.
Now if you create an instance of your socket class you have to connect the handler and set the EventsEnabled true.
This handler then calls the shutdown and your socket does not stay in FIN_WAIT_2
Socket programming, ASP.Net C#, VS2008
I am trying to determine whether the status of remote(client) is connected or disconnected on every 5 second through timer control. Whenever I start the server first time I getting the socket status is connected=true. But next time I getting socket status is null.
Note: I am Accessing a Socket status from class to Aspx page through creating object of a class.
This is my code:
Aspx page:
protected void Timer1_Tick1(object sender, EventArgs e)
{
Communication obj=new communication();
bool Rexits=obj.listen();
if(Rexits)
Response.write("Remote is On");
else
Response.write("Remote is Off");
}
**************************************************************************
Communication class:
Socket listener=new Socket();
Socket connection;
public bool listen()
{
listener.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress, true);
bool RemoteExits = false;
try
{
if (connection== null)
{
listener.Bind(endPoint);
listener.Listen(pendingConnectionQueueSize);
listener.BeginAccept(AcceptConnection, null);
RemoteExits = IsConnected(connection);
}
return RemoteExits;
}
catch (Exception ex)
{
a = IsConnected(connection);
return RemoteExits;
}
}
//callback method
protected void AcceptConnection(IAsyncResult res)
{
// Make sure listener doesn't go null on us.
lock (this)
{
connection = listener.EndAccept(res);
listener.BeginAccept(AcceptConnection, null);
}
// Close the connection if there are no handlers to accept it!
if (Connected == null)
{
connection.Close();
}
else
{
TcpServer tc=new TcpServer();
Clifton.TcpLib.ConnectionState cs=new
Clifton.TcpLib.ConnectionState(connection,cs);
OnConnected(new TcpServerEventArgs(cs));
}
}
//Poll Mehod
public static bool IsConnected(Socket client)
{
try
{
bool connected = !(client.Poll(1, SelectMode.SelectRead) &&
client.Available == 0);
return connected;
}
catch
{
return false;
}
}
Im writing an application which is going to act as a tcp listener for a single client. The client is a java applet and will periodically connect to the listener, send some data and then wait for a response.
The code for the TcpServer class below has been largely lifted from an example provided by a more knowledgeable stackoverflow member in response to a different question.
Everything was going great until I found something in testing which wasnt mentioned in any of the interface documents I have. After the server has responded to the client it must then disconnect the client and start listening again.
My first thought was to call Disconnect() from inside SendData() but this results in a call to ReceiveCompleted() from somewhere and a nasty exception about the socket already being disposed.
Is this requirement easily achievable with the code design I have, and will I run into any problems in reusing the socket for subsequent connections?
sealed class TcpServer : IDisposable
{
#region Fields
private const int SocketBufferSize = 1024;
private readonly TcpListener tcpListener;
private Socket connectedSocket;
private bool disposed = false;
#endregion Fields
#region Constructors
public TcpServer(int port)
{
tcpListener = new TcpListener(IPAddress.Any, port);
tcpListener.Start();
tcpListener.BeginAcceptSocket(EndAcceptSocket, tcpListener);
}
~TcpServer()
{
Dispose(false);
}
#endregion Constructors
#region Events
public event EventHandler<DataReceivedEventArgs> DataReceived;
public event EventHandler<IPEndPointEventArgs> SocketConnected;
public event EventHandler<IPEndPointEventArgs> SocketDisconnected;
#endregion Events
#region Methods
public void Dispose()
{
Dispose(true);
}
public void SendData(byte[] data)
{
if (connectedSocket == null)
{
return;
}
connectedSocket.Send(data);
}
private void BeginReceiveAsync(Socket sock, SocketAsyncEventArgs e)
{
if (!sock.ReceiveAsync(e))
{
ReceiveCompleted(sock, e);
}
}
private void Connected(Socket socket)
{
var endPoint = (IPEndPoint)socket.RemoteEndPoint;
connectedSocket = socket;
OnSocketConnected(endPoint);
}
private void Disconnect(Socket socket)
{
var endPoint = (IPEndPoint)socket.RemoteEndPoint;
socket.Close();
connectedSocket = null;
OnSocketDisconnected(endPoint);
tcpListener.BeginAcceptSocket(EndAcceptSocket, tcpListener);
}
private void Dispose(bool disposing)
{
if (this.disposed == false)
{
if (disposing)
{
try
{
if (tcpListener != null)
{
this.disposed = true;
tcpListener.Stop();
}
}
catch (Exception ex)
{
TraceLog.Error("TcpServer: tcpListener.Stop(): {0}", ex.Message);
}
try
{
if (connectedSocket != null)
{
connectedSocket.Close();
connectedSocket = null;
}
}
catch (SocketException ex)
{
TraceLog.Error("TcpServer: connectedSocket.Close(): {0}", ex);
}
}
this.disposed = true;
}
}
private void EndAcceptSocket(IAsyncResult asyncResult)
{
var listener = (TcpListener)asyncResult.AsyncState;
if (disposed)
{
return;
}
try
{
Socket sock = listener.EndAcceptSocket(asyncResult);
Connected(sock);
var e = new SocketAsyncEventArgs();
e.Completed += ReceiveCompleted;
e.SetBuffer(new byte[SocketBufferSize], 0, SocketBufferSize);
BeginReceiveAsync(sock, e);
}
catch (SocketException ex)
{
TraceLog.Error("TcpServer.EndAcceptSocket: {0}", ex.Message);
}
catch (Exception ex)
{
TraceLog.Error("TcpServer.EndAcceptSocket: {0}", ex.Message);
}
}
private void OnDataReceived(byte[] data, IPEndPoint ipEndPoint)
{
if (DataReceived != null)
{
DataReceived(this, new DataReceivedEventArgs(data, ipEndPoint));
}
}
private void OnSocketConnected(IPEndPoint ipEndPoint)
{
if (SocketConnected != null)
{
SocketConnected(this, new IPEndPointEventArgs(ipEndPoint));
}
}
private void OnSocketDisconnected(IPEndPoint ipEndPoint)
{
if (SocketDisconnected != null)
{
SocketDisconnected(this, new IPEndPointEventArgs(ipEndPoint));
}
}
private void ReceiveCompleted(object sender, SocketAsyncEventArgs e)
{
var sock = (Socket)sender;
if (!sock.Connected)
{
Disconnect(sock);
}
try
{
int size = e.BytesTransferred;
if (size == 0)
{
Disconnect(sock);
}
else
{
var buf = new byte[size];
Array.Copy(e.Buffer, buf, size);
ReceiveData(buf, (IPEndPoint)sock.RemoteEndPoint);
BeginReceiveAsync(sock, e);
}
}
catch (SocketException ex)
{
TraceLog.Error("TcpServer: ReceiveCompleted: {0}", ex.Message);
}
catch (Exception ex)
{
TraceLog.Error("TcpServer: ReceiveCompleted: {0}", ex.Message);
}
}
private void ReceiveData(byte[] data, IPEndPoint endPoint)
{
OnDataReceived(data, endPoint);
}
#endregion Methods
}
Whenever I'm writing code that wraps around System.Net.Sockets.Socket, I find myself constantly adding try/catch clauses for SocketException and ObjectDisposedException. In most cases, ObjectDisposedException can simply be ignored, as it, in 99% of cases, indicates that the client has simply disconnected.
At least that's my impression of how the Socket API in .NET works. Try adding some exception handlers here and there, and see how it goes. In any case, your Disconnect method should not do more than something like this:
public void Disconnect()
{
try
{
connectedSocket.Shutdown(SocketShutdown.Both);
}
catch (Exception)
{
// Ignore the exception. The client probably already disconnected.
}
connectedSocket.Dispose(); // This is safe; a double dispose will simply be ignored.
}
I hope that sheds some light on the issue...