C# TCP Server using infinite Loop unexpectedly closes - c#

I am currently developing a C# TCP Server application for my game. The Server functions perfectly for a long period of time, closes however unexpectedly after about a day or 2 of running. I've furthermore printed the console output to a file, which I checked after the application closed, and there were no errors, or at least none were printed. The Code for the server is the following :
class Program
{
private static Thread consoleThread;
static void Main(string[] args)
{
//To get the output in a file
FileStream filestream = new FileStream("out.txt", FileMode.Create);
var streamwriter = new StreamWriter(filestream);
streamwriter.AutoFlush = true;
Console.SetOut(streamwriter);
Console.SetError(streamwriter);
InitializeConsoleThread();
ServerHandleData.InitializePacketListener();
ServerTCP.InitializeServer();
}
private static void InitializeConsoleThread()
{
consoleThread = new Thread(ConsoleLoop);
consoleThread.Name = "ConsoleThread";
consoleThread.Start();
}
private static void ConsoleLoop()
{
while (true)
{
}
}
}
The TCP Clients are handled with the following async methods :
private static void InitializeServerSocket()
{
ServerSocket = new TcpListener(IPAddress.Any, 8080);
ServerSocket.Start();
ServerSocket.BeginAcceptTcpClient(ClientConnectCallback, null); //Once we get a connection, ClientConnectCallback is called
}
private static void ClientConnectCallback(IAsyncResult result)
{
TcpClient tempClient = ServerSocket.EndAcceptTcpClient(result); //Accepts the connection and creates its corresponding TcpClient
ServerSocket.BeginAcceptTcpClient(ClientConnectCallback, null); //Open the connection again for other players
string[] IPs = tempClient.Client.RemoteEndPoint.ToString().Split(':');
if(IPDictionary.TryGetValue(IPs[0], out ClientObject C))
{
C.Socket = tempClient;
C.Socket.NoDelay = true;
C.Socket.ReceiveBufferSize = 4096;
C.Socket.SendBufferSize = 4096;
C.ReceiveBuffer = new byte[4096];
C.myStream = C.Socket.GetStream();
C.IP = tempClient.Client.RemoteEndPoint.ToString();
C.myStream.BeginRead(C.ReceiveBuffer, 0, C.Socket.ReceiveBufferSize, C.ReceiveCallback, null);
PACKET_SendMessage(C.ConnectionID, "CheckIP", 0, IPs[0]);
Console.WriteLine("Connection incoming from {0}", C.IP);
return;
}
Random ran = new Random();
int curID = ran.Next(); //random signed int
while (curID == 0 || ClientObjects.ContainsKey(curID)) { curID = ran.Next(); }
ClientObjects[curID] = new ClientObject(tempClient, curID);
TempPlayers[curID] = new TempPlayer();
}
which are called in the Program class with the initializeServer methods.
The Server functions well for a while and then suddenly closes, seemingly without any reason. The only cause I could find while searching on the internet is that the program eventually runs out of memory and just closes. Wouldn't however the garbage collector integrated in C# prevent such a thing ? Thank you all for your help in advance, I hope I made the question as direct and as clear as possible. Furthermore, if there are any other ways to improve these snippets of code, please do tell.

Related

C#/WPF/Unity namepipes communication sends messages just in one direction

I got stuck in solving a problem in my current project. I'm coding a simulation in WPF/C# and included a Unity-Application in the window using the window-handles/hwnd pretty much like "Programmer" did in this answer. He also suggested namedpipes for the communication.
But the communication just works in one way - The server (WPF-App) is able to send messages to the client (the embedded Unity-App). If I try it the other way around, the whole Unity-App hungs up and stops working. As far as I was able to figure it out, as soon as I flush the writer or add the AutoFlush and then write something Unity gets stuck.
It is interesting, that the InBufferSize of the server is 0. Might this be the Problem?
This is my C#-Script in Unity assigned to a GameObject:
public class pipeCommunicationScript : MonoBehaviour
{
NamedPipeClientStream client;
public GameObject console;
static Text consoleText;
StreamReader reader;
StreamWriter writer;
int counter = 0;
static bool _threadRunning;
Thread _thread;
void Start()
{
consoleText = console.GetComponent<Text>();
consoleText.text = "trying to set up client";
_thread = new Thread(StartClient);
_thread.Start();
}
void StartClient()
{
_threadRunning = true;
//Client
consoleText.text = "Attempting to connect to pipe...";
client = new NamedPipeClientStream(".","UnitySimulationPipe", PipeDirection.InOut);
if (!client.IsConnected) { client.Connect(); }
consoleText.text = "Connected to pipe.";
writer = new StreamWriter(client);
reader = new StreamReader(client);
writer.AutoFlush = true;
InvokeRepeating("sendThroughPipe", 5.5f, 5.5f);
while (_threadRunning)
{
consoleText.text = "IN:" + reader.ReadLine();
}
_threadRunning = false;
}
void sendThroughPipe()
{
try
{
client.WaitForPipeDrain();
writer.WriteLine("test" + counter);
}
catch(Exception e)
{
consoleText.text = "Exception while sending: " + e;
}
consoleText.text = "OUT: test" + counter;
counter++;
}
void OnDisable()
{
if (_threadRunning)
{
_threadRunning = false;
_thread.Join();
}
}
}
And this my Server-Script:
void StartServer()
{
Task.Factory.StartNew(() =>
{
Console.WriteLine("Connection initialisation started");
var server = new NamedPipeServerStream("UnitySimulationPipe", PipeDirection.InOut);
server.WaitForConnection();
while (!server.IsConnected)
{
Console.WriteLine("Connection not initialized");
server.WaitForConnection();
}
Console.WriteLine("Connection initialized");
reader = new StreamReader(server);
writer = new StreamWriter(server);
writer.AutoFlush = true;
writer.WriteLine("startConnection");
printOnStatusBar("OUT: startConnection");
connected = true;
Console.WriteLine("Current pipe readable: " + server.CanRead);
Console.WriteLine("Pipe InBufferSize: " + server.InBufferSize);
while (true)
{
Console.WriteLine("start while again");
if (reader.Peek() > 0)
{
var l = reader.ReadLine();
Console.WriteLine(reader.ReadLine());
Console.WriteLine("read finished");
server.WaitForPipeDrain();
}
Thread.Sleep(500);
}
});
}
The most probable answer is, in fact, what you mentionned (bufferSize).
You should check for the initialyzers parameters of every object you use.
Don't worry, I'm sure you'll find the answer just by searching there. I used to create such code in the same way, it should work well.
Okay, I changed my initilisation of the server-object to (explanation of different parameters here):
var server = new NamedPipeServerStream("UnitySimulationPipe", PipeDirection.InOut, 1, 0, 0, 1024, 1024);
But I personally think, that this was just a minor mistake. The mainreason why my code didn't worked was, that I missed to call
server.WaitForPipeDrain();
after
writer.WriteLine("startConnection");
printOnStatusBar("OUT: startConnection");
in my server-code.

c# renci ssh command output differs from client to client

Something really odd is happening to me.
I have ssh command which executes python script on my remote server.
When I execute it through PuTTY it works like it should and desired output is shown. But when executed through my C# app using ssh.net it always returns some old data that's long time gone from the server (which is freebsd 9.3).
Here's how I execute my command and catch output:
var task = new Task(() => {
var ret = ssh_instance.CreateCommand("cd /home/" + "python python_script.py -param");
ret.Execute();
FlexibleMessageBox.Show(ret.Result);
});
task.Start();
It seems literally unexplainable to me so I would be really thankful if someone could enlighten me what am I doing wrong.
Please remember.
Connection will closed after calling "CreateCommand()" method.
You need to read all of received data from your stream against your each command.
--> In my opinion, this is a reason why you've got old result from your connection.
So, I try to use Renci.SshNet.ShellStream class. in my code was,
private Renci.SshNet.SshClient _client = null;
private Renci.SshNet.ShellStream shellStream = null;
private void connect()
{
try
{
this.disConnect();
_client = new Renci.SshNet.SshClient(cboUri.Text, tbxSrvUsr.Text, tbxSrvPW.Text);
//_client.ErrorOccurred += new EventHandler<Renci.SshNet.Common.ExceptionEventArgs>(_client_ErrorOccurred);
//_client.HostKeyReceived += new EventHandler<Renci.SshNet.Common.HostKeyEventArgs>(_client_HostKeyReceived);
_client.Connect();
byte[] buffer = new byte[1000];
shellStream = _client.CreateShellStream("Jornathan", 80, 24, 800, 800, 1024);
shellStream.BeginRead(buffer, 0, buffer.Length, null, null);
shellStream.DataReceived += new EventHandler<Renci.SshNet.Common.ShellDataEventArgs>(shellStream_DataReceived);
tbxStatus.Text = "Connected";
this.btnConnect.Enabled = false;
this.cboServerList.Enabled = false;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
and add method to read all text from server.
Please remember, you should read all text until encounter received data size is "0". refer as below.
private void readOutput()
{
do
{
string strOutput = shellStream.ReadLine();
if (strOutput != null && strOutput.Length > 0)
{
System.Console.WriteLine(strOutput);
this.SetStatusText(strOutput);
}
else
{
break;
}
} while (true);
}
And then add event handler, that's it!.
private System.Threading.Thread Thread_OutputHandle = null;
private void shellStream_DataReceived(object sender, Renci.SshNet.Common.ShellDataEventArgs e)
{
if (Thread_OutputHandle == null)
{
Thread_OutputHandle = new System.Threading.Thread(new System.Threading.ThreadStart(readOutput));
Thread_OutputHandle.Start();
}
else if (Thread_OutputHandle.ThreadState == System.Threading.ThreadState.Stopped)
{
Thread_OutputHandle.Abort();
Thread_OutputHandle = new System.Threading.Thread(new System.Threading.ThreadStart(readOutput));
Thread_OutputHandle.Start();
}
}
Others:
I hope to remember where I've got help to make this code.
but I can't.
Please let me know when you find location of code that I've got help.
I'll add its location to here.

Waiting for HID Card Reader to be Connected

I am writing an application that requires an HID card reader be connected to the system. Everything works properly when a card reader is already connected when the application is started, so I know I can find the device properly. (I am using the HID classes from PM> Install-Package hidlibrary.)
I want to add a feature where the program will display a prompt to connect a card reader if one is not found.
This is my first attempt:
public class App : Application
{
public static List<HidDevice> HidDeviceList;
// Block until device is plugged in
static ManualResetEvent m_WaitForPlugin = new ManualResetEvent(false);
// WMI Watcher for actual plug-in event
static ManagementEventWatcher watcher = new ManagementEventWatcher();
[STAThread()]
static void Main()
{
ShowSplashScreen();
FindCardReader();
CloseSplashScreen();
new App();
}
public App() : base()
{
StartupUri = new System.Uri("MainWindow.xaml", UriKind.Relative);
Run();
}
private static void FindCardReader()
{
ShowOnSplashScreen("Searching for card reader");
do
{
int VendorID = Convert.ToInt32(Settings.Default.ReaderVID, 16); // 0x0801
int ProductID = Convert.ToInt32(Settings.Default.ReaderPID, 16); // 0x0002
HidDeviceList = HidDevices.Enumerate(VendorID, ProductID).ToList();
if (HidDeviceList.Count > 0) {
break;
}
ShowOnSplashScreen("Please attach card reader...");
SetupWatcher();
m_WaitForPlugin.WaitOne();
} while (HidDeviceList.Count == 0);
}
private static void SetupWatcher()
{
WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
watcher.EventArrived += new EventArrivedEventHandler(delegate(Object sender, EventArrivedEventArgs e)
{
ShowOnSplashScreen("New device detected!");
m_WaitForPlugin.Set();
});
watcher.Query = query;
watcher.Start();
}
FindCardReader() in Main blocks as expected, but never appears to be signalled when a new device is plugged in. (I put a breakpoint in the delegate and it was never hit.)
I am not sure how to test the WMI watcher by itself (I tested the query in PowerShell and it appears to work). I also tried starting it in a new Thread, but the result was the same.
It turns out that there is a very clear deadlock in this code. I have re-architected the entire system to avoid the issue rather than add additional threads to handle the locking.

C# Multicast UDP connection, BeginReceiveFrom async call stops to be called

this is my first post, sorry in advance if I do something I shouldn't. I always search here for answer but this time I saw nothing about my problem. I have a project in C# where I keep alive a connection UDP listening a multicast IP from a data streaming.
The IP I'm listening is a multicast streamer that sends tracking data from many tracking systems, so we can assume the sender is not the problem. It sends like 1024 bytes packets, 60 fps.
This is a small example extracted from the whole project, simplified and as far as I tested, behaves in the same way as in the big project. The problem is that if I connect in localhost this never break, but if I connect to remote IPs this stop working, more or less, in 4 minutes.
public class TrackingStateObject
{
public Socket workSocket = null;
public const int BUFFER_SIZE = 65507;
public byte[] buffer = new byte[BUFFER_SIZE];
}
class MainClass
{
static public string multicastServerIPAddress = "239.255.42.99";
static public string realTrackingServerIPAddress = "161.116.27.144";
static protected EndPoint trackingEndPoint;
static public int dataPort = 2345;
static protected Socket sockData = null;
static int foo = 0;
public static void Main (string[] args)
{
IPEndPoint ipep;
TrackingStateObject so;
IPAddress trackingIP = IPAddress.Parse(multicastServerIPAddress);
trackingEndPoint = new IPEndPoint(trackingIP, dataPort);
sockData = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
ipep = new IPEndPoint(IPAddress.Any, dataPort);
try {
sockData.Bind(ipep);
}
catch (Exception ex) {
System.Console.WriteLine("[UDPClient] Exception "+ex.Message);
return;
}
sockData.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(trackingIP));
try {
trackingIP = IPAddress.Parse(realTrackingServerIPAddress);
trackingEndPoint = new IPEndPoint(trackingIP, dataPort);
}
catch(Exception ex) {
System.Console.WriteLine("[UDPClient] Exception "+ex.Message);
return;
}
so = new TrackingStateObject();
so.workSocket = sockData;
sockData.BeginReceiveFrom(so.buffer, 0, TrackingStateObject.BUFFER_SIZE, 0, ref trackingEndPoint, new AsyncCallback(AsyncReceiveCallback), so);
System.Threading.Thread.Sleep (600000);
}
private static void AsyncReceiveCallback(IAsyncResult ar)
{
try {
TrackingStateObject so = (TrackingStateObject)ar.AsyncState;
Socket sock = so.workSocket;
int read = sock.EndReceiveFrom(ar, ref trackingEndPoint);
if (read > 0)
{
// Do things with the data
System.Console.WriteLine("Recieved shit, " + read + " bytes, " + foo++ + " times.");
}
sock.BeginReceiveFrom(so.buffer, 0, TrackingStateObject.BUFFER_SIZE, SocketFlags.None, ref trackingEndPoint, new AsyncCallback(AsyncReceiveCallback), so);
}
catch (Exception e) {
System.Console.WriteLine("[UDPClient] Exception AsynCallback "+e.Message);
}
}
}
I debugged for a while and as far I can see is that always sock.BeginReceiveFrom is called, stop in some point, AsyncReceiveCallback is never executed again. Perhaps I'm doing here something stupid, but in any case, I'm not able to see it. Thanks!
I was having exactly the same problem, which only seems to occur on WiFi interfaces, not hardwired interfaces. The solution I discovered was to always set the SocketOptionName.AddMembership option before calling BeginReceiveFrom().
In the receive callback, after calling EndReceiveFrom() then set the SocketOptionName.DropMembership option for the multicast address.
Then before calling BeginReceiveFrom() again, set the SocketOptionName.AddMembership option.
Not sure why this has to be done for WiFi interfaces, but it worked for me.

C# Sockets: Automatically receiving messages

I am rather new to C# and Sockets however I am trying my hand at making a kind of "chat" program. What I am having an issue with at the moment is making the client able to automatically receive a message from the server if one is available.
What I have tried so far:
System.Threading.Thread myThread = new System.Threading.Thread(new
System.Threading.ThreadStart(listenThread));
public static void listenThread()
{
while(true){
Form1 form1 = new Form1();
form1.ReceiveLoop();
}
}
private void ReceiveLoop()
{
clientSocket.ReceiveTimeout = 100;
byte[] receivedBuffer = new byte[1024];
try
{
int rec = clientSocket.Receive(receivedBuffer);
byte[] data = new byte[rec];
Array.Copy(receivedBuffer, data, rec);
updateClient("Received: " + Encoding.ASCII.GetString(data));
}
catch (SocketException e)
{
//MessageBox.Show(e.ToString());
}
}
ReceiveLoop() works when I access from the GUI thread, however it will not work(Throws SocketException, due to timeout) when accessed via myThread.
Any help or suggestions on another way I could approach this would be greatly appreciated :D

Categories

Resources