Console application crashing - c#

Hi guys i have here a console application written in c# ,
I have spend all my week finding and looking for the reason why it sometimes suddenly crashing,
this console app is running continuously, no closing means when i run it it will kept running no shutting down of computer
I put every method with try catch and every catch exception it will write it to the logs
but when the application crashed there's no logs so that means there's exception that not being handled
can some one help find the possible reason why.
I'm drop off the whole code here.
class Program
{
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
protected static string server_hostname = ConfigurationManager.AppSettings["ServerHostname"];
protected static string copychimp_server = "";
protected static int port_number = 0;
private static byte[] _buffer = new byte[10000];
private static List<Socket> _clientSockets = new List<Socket>();
private static Socket _serverSocket = new Socket(Dns.GetHostEntry(ConfigurationManager.AppSettings["ServerHostname"]).AddressList[0].AddressFamily, SocketType.Stream, ProtocolType.Tcp);
private static Dictionary<string, DateTime> dict_cmd_lastsent = new Dictionary<string, DateTime>();
private static Dictionary<string, double> dict_cmd_interval = new Dictionary<string, double>();
private static Dictionary<string, string> dict_drive = new Dictionary<string, string>();
private static Dictionary<string, string> dict_host = new Dictionary<string, string>();
static bool ConsoleEventCallback(int eventType)
{
if (eventType == 2)
{
}
return false;
}
static ConsoleEventDelegate handler; // Keeps it from getting garbage collected
// Pinvoke
private delegate bool ConsoleEventDelegate(int eventType);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetConsoleCtrlHandler(ConsoleEventDelegate callback, bool add);
static void Main(string[] args)
{
Console.Write(" Enter copychimp server: ");
copychimp_server = Console.ReadLine();
Console.Write("Enter port number: ");
port_number = Convert.ToInt16(Console.ReadLine());
//copychimp_server = args[0].ToString().Trim();
//port_number = Convert.ToInt16(args[1]);
//Thread.Sleep(3000);
try
{
var server_logs_dir = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "\\logs\\" + copychimp_server;
var server_config_dir = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "\\config";
var server_config = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "\\config\\" + copychimp_server + ".config";
if (!Directory.Exists(server_config_dir))
{
Directory.CreateDirectory(server_config_dir);
}
if (!Directory.Exists(server_logs_dir))
{
Directory.CreateDirectory(server_logs_dir);
}
var config = "";
config += "<port>" + port_number + "</port>";
config += Environment.NewLine;
try
{
var pid = GetTagValue(File.ReadAllText(server_config), "PID");
var test_pid = Process.GetProcessById(Convert.ToInt16(pid));
var pname = test_pid.ProcessName;
ServerLogs(pname + " is currently active using PID (" + pid + ")");
config += "<PID>" + pid + "</PID>";
File.WriteAllText(server_config, config);
}
catch (Exception ex)
{
config += "<PID>" + Process.GetCurrentProcess().Id + "</PID>";
File.WriteAllText(server_config, config);
handler = new ConsoleEventDelegate(ConsoleEventCallback);
const int SW_HIDE = 0;
var handle = GetConsoleWindow();
ShowWindow(handle, SW_HIDE); // To hide
ServerStarted();
Console.ReadKey();
}
}
catch (Exception ex)
{
ServerLogs("Main error: " + ex.Message.ToString());
}
}
private static void ServerStarted()
{
try
{
IPHostEntry hostEntry = Dns.GetHostEntry(server_hostname);
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port_number);
ServerLogs("CopyChimpServer.exe Started. Waiting for connection...");
_serverSocket.Bind(localEndPoint);
_serverSocket.Listen(1);
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
catch (SocketException ex)
{
ServerLogs("ServerStarted Error " + ex.Message.ToString());
}
}
private static string ServerCommand(string hostname)
{
var command = "";
try
{
CopyChimpDB copychimp_db = new CopyChimpDB();
DataTable dt_robocopy = copychimp_db.GetCopyChimp("GetCommand", hostname, "");
if (dt_robocopy.Rows.Count == 1)
{
command = dt_robocopy.Rows[0]["command"].ToString();
}
else if (dt_robocopy.Rows.Count > 1)
{
ServerLogs(hostname + " GetCommand error: Returns more than 1 row.");
}
}
catch (Exception ex)
{
ServerLogs(hostname + " ServerCommand error " + ex.ToString());
}
return command;
}
private static void ReceiveCallBack(IAsyncResult AR)
{
Thread.Sleep(1000);
Socket socket = null;
string hostname = "";
string ip_address = "";
CopyChimpDB copychimp_db = new CopyChimpDB();
try
{
socket = (Socket)AR.AsyncState;
int received = socket.EndReceive(AR);
ip_address = (socket.RemoteEndPoint as IPEndPoint).ToString().Split(':')[0];
hostname = dict_host[ip_address];
byte[] dataBuff = new byte[received];
Array.Copy(_buffer, dataBuff, received);
string message_to_client = "wait";
if (Convert.ToDouble(Math.Round((DateTime.Now - Convert.ToDateTime(dict_cmd_lastsent[hostname])).TotalMinutes, 2)) >= dict_cmd_interval[hostname])
{
var server_command = ServerCommand(hostname);
if (server_command.Trim() != "")
{
//string message_from_client = WebUtility.HtmlDecode(Encoding.ASCII.GetString(dataBuff));
message_to_client += "<DriveName>" + dict_drive[hostname] + "</DriveName>";
message_to_client += "<ServerCommand>" + ServerCommand(hostname) + "</ServerCommand>";
try
{
copychimp_db.PostCopyChimp("ConnectMachine", hostname, ip_address);
}
catch (Exception oraex)
{
ServerLogs(hostname + "--" + oraex.ToString());
}
dict_cmd_lastsent[hostname] = DateTime.Now;
//ServerLogs(hostname + " updated");
}
}
byte[] data = Encoding.ASCII.GetBytes(message_to_client);
socket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), socket);
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
}
catch (SocketException ex)
{
try
{
//_clientSockets.Remove(socket);
ServerLogs(hostname + " SocketException! " + ex.Message.ToString());
if (hostname != "")
{
try
{
copychimp_db.PostCopyChimp("DisconnectMachine", hostname, ip_address);
}
catch (Exception oraex)
{
ServerLogs(hostname + "--" + oraex.ToString());
}
}
}
catch (Exception ex_)
{
ServerLogs(hostname + " DisconnectMachine error! " + ex_.ToString());
}
}
}
private static Thread thread;
private static void AcceptCallback(IAsyncResult AR)
{
string hostname = "";
try
{
CopyChimpDB copychimp_db = new CopyChimpDB();
Socket socket = _serverSocket.EndAccept(AR);
string ip_address = "";
//hostname checking
ip_address = (socket.RemoteEndPoint as IPEndPoint).ToString().Split(':')[0];
try
{
try
{
hostname = Dns.GetHostEntry(ip_address).HostName;
}
catch (Exception host_ex)
{
ServerLogs(ip_address + " GetHostEntry error: " + host_ex.Message.ToString());
DataTable dt_ip = copychimp_db.GetCopyChimp("GetHostnameByIpAddress", hostname, ip_address);
if (dt_ip.Rows.Count == 1)
{
hostname = dt_ip.Rows[0]["hostname"].ToString();
ServerLogs(ip_address + " GetHostnameByIpAddress : " + hostname);
}
}
DataTable dt_hostname = copychimp_db.GetCopyChimp("GetHostname", hostname, ip_address);
hostname = "";
if (dt_hostname.Rows.Count == 1)
{
hostname = dt_hostname.Rows[0]["hostname"].ToString();
}
else if (dt_hostname.Rows.Count > 1)
{
ServerLogs(hostname + " GetHostname error: Returns more than 1 row.");
}
if (hostname != "")
{
if (!_clientSockets.Contains(socket))
{
dict_host[ip_address] = hostname;
_clientSockets.Add(socket);
copychimp_db.PostCopyChimp("ConnectMachine", hostname, ip_address);
/*------------------------------------------------------------------------------------------------*/
dict_cmd_interval[hostname] = Convert.ToDouble(copychimp_db.GetCopyChimp("GetInterval", hostname, ip_address).Rows[0]["interval"].ToString());
/*------------------------------------------------------------------------------------------------*/
dict_cmd_lastsent[hostname] = Convert.ToDateTime(copychimp_db.GetCopyChimp("GetLastUpdate", hostname, ip_address).Rows[0]["lastupdate"]);
/*------------------------------------------------------------------------------------------------*/
dict_drive[hostname] = copychimp_db.GetCopyChimp("GetDriveName", hostname, ip_address).Rows[0]["drive_name"].ToString();
/*------------------------------------------------------------------------------------------------*/
thread = new Thread(() =>
{
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
});
thread.Start();
ServerLogs(hostname + " connected");
}
}
}
catch (Exception oraex)
{
ServerLogs(hostname + "--" + oraex.ToString());
}
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
catch (SocketException ex)
{
ServerLogs("AcceptCallback SocketException " + hostname + ex.Message.ToString());
}
}
private static void SendCallback(IAsyncResult AR)
{
Socket socket = (Socket)AR.AsyncState;
socket.EndSend(AR);
}
private static void ServerLogs(string text)
{
bool logging_success = false;
try
{
string logpath = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "\\logs\\" + copychimp_server + "\\" + DateTime.Now.ToString("yyyyMMdd") + ".log";
do
{
try
{
string log = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]" + " " + text + Environment.NewLine;
if (!File.Exists(logpath))
{
File.WriteAllText(logpath, log);
}
else
{
File.AppendAllText(logpath, log);
}
logging_success = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
} while (logging_success == false);
}
catch (Exception ex)
{
//send emai
}
}
private static string GetTagValue(string text, string tag)
{
var result = "";
try
{
var start_tag = "<" + tag + ">";
var end_tag = "</" + tag + ">";
int pFrom = text.IndexOf(start_tag) + start_tag.Length;
int pTo = text.LastIndexOf(end_tag);
result = text.Substring(pFrom, pTo - pFrom);
}
catch (Exception ex)
{
ServerLogs("GetTagValue() error " + ex.Message.ToString());
}
return result;
}
}
A help a highly appreciated thank you in advance.
I need to log it on the DB before the crushing occurred and i'm going to use it as reference for a new automatic emailing if the app crashed.

Related

Socket Begin Receiving Error crash whole application even with a try/catch

I have this console application written in c# running as service on the server. It can run sucessfully for a days and many connections but at some points the service crash with this exception on Windows event viewer.
Application: CopyChimpServer.exe Framework Version: v4.0.30319 Description:
The process was terminated due to an unhandled exception. Exception Info:
System.Net.Sockets.SocketException at System.Net.Sockets.Socket.BeginReceive(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags,
System.AsyncCallback, System.Object) at CopyChimpServer.Program+<>c__DisplayClass2.<AcceptCallback>b__0()
at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,
System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,
System.Threading.ContextCallback, System.Object)
at System.Threading.ThreadHelper.ThreadStart()
my code is this with many try catch to hadle it but did not work,
private static void ReceiveCallBack(IAsyncResult AR)
{
Thread.Sleep(1000);
Socket socket = null;
string hostname = "";
string ip_address = "";
CopyChimpDB copychimp_db = new CopyChimpDB();
try
{
socket = (Socket)AR.AsyncState;
int received = socket.EndReceive(AR);
ip_address = (socket.RemoteEndPoint as IPEndPoint).ToString().Split(':')[0];
hostname = dict_host[ip_address];
byte[] dataBuff = new byte[received];
Array.Copy(_buffer, dataBuff, received);
string message_to_client = "wait";
if (Convert.ToDouble(Math.Round((DateTime.Now - Convert.ToDateTime(dict_cmd_lastsent[hostname])).TotalMinutes, 2)) >= dict_cmd_interval[hostname])
{
var server_command = ServerCommand(hostname);
if (server_command.Trim() != "")
{
//string message_from_client = WebUtility.HtmlDecode(Encoding.ASCII.GetString(dataBuff));
message_to_client += "<DriveName>" + dict_drive[hostname] + "</DriveName>";
message_to_client += "<ServerCommand>" + ServerCommand(hostname) + "</ServerCommand>";
try
{
copychimp_db.PostCopyChimp("ConnectMachine", hostname, ip_address);
}
catch (Exception oraex)
{
ServerLogs(hostname + "--" + oraex.ToString());
}
dict_cmd_lastsent[hostname] = DateTime.Now;
//ServerLogs(hostname + " updated");
}
}
byte[] data = Encoding.ASCII.GetBytes(message_to_client);
socket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), socket);
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
//socket.BeginReceive(_buffer,0,_buffer.Length,SocketFlags.None,new AsyncCallback(ReceiveCallBack),)
}
catch (SocketException ex)
{
try
{
//_clientSockets.Remove(socket);
ServerLogs(hostname + " SocketException! " + ex.Message.ToString());
if (hostname != "")
{
try
{
copychimp_db.PostCopyChimp("DisconnectMachine", hostname, ip_address);
}
catch (Exception oraex)
{
ServerLogs(hostname + "--" + oraex.ToString());
}
}
}
catch (Exception ex_)
{
ServerLogs(hostname + " DisconnectMachine error! " + ex_.ToString());
}
}
}
private static Thread thread;
private static void AcceptCallback(IAsyncResult AR)
{
string hostname = "";
try
{
CopyChimpDB copychimp_db = new CopyChimpDB();
Socket socket = _serverSocket.EndAccept(AR);
string ip_address = "";
//hostname checking
ip_address = (socket.RemoteEndPoint as IPEndPoint).ToString().Split(':')[0];
try
{
try
{
hostname = Dns.GetHostEntry(ip_address).HostName;
}
catch (Exception host_ex)
{
ServerLogs(ip_address + " GetHostEntry error: " + host_ex.Message.ToString());
DataTable dt_ip = copychimp_db.GetCopyChimp("GetHostnameByIpAddress", hostname, ip_address);
if (dt_ip.Rows.Count == 1)
{
hostname = dt_ip.Rows[0]["hostname"].ToString();
ServerLogs(ip_address + " GetHostnameByIpAddress : " + hostname);
}
}
DataTable dt_hostname = copychimp_db.GetCopyChimp("GetHostname", hostname, ip_address);
hostname = "";
if (dt_hostname.Rows.Count == 1)
{
hostname = dt_hostname.Rows[0]["hostname"].ToString();
}
else if (dt_hostname.Rows.Count > 1)
{
ServerLogs(hostname + " GetHostname error: Returns more than 1 row.");
}
if (hostname != "")
{
if (!_clientSockets.Contains(socket))
{
dict_host[ip_address] = hostname;
_clientSockets.Add(socket);
copychimp_db.PostCopyChimp("ConnectMachine", hostname, ip_address);
/*------------------------------------------------------------------------------------------------*/
dict_cmd_interval[hostname] = Convert.ToDouble(copychimp_db.GetCopyChimp("GetInterval", hostname, ip_address).Rows[0]["interval"].ToString());
/*------------------------------------------------------------------------------------------------*/
dict_cmd_lastsent[hostname] = Convert.ToDateTime(copychimp_db.GetCopyChimp("GetLastUpdate", hostname, ip_address).Rows[0]["lastupdate"]);
/*------------------------------------------------------------------------------------------------*/
dict_drive[hostname] = copychimp_db.GetCopyChimp("GetDriveName", hostname, ip_address).Rows[0]["drive_name"].ToString();
/*------------------------------------------------------------------------------------------------*/
thread = new Thread(() =>
{
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
});
thread.Start();
ServerLogs(hostname + " connected");
}
}
}
catch (Exception oraex)
{
ServerLogs(hostname + "--" + oraex.ToString());
}
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
catch (SocketException ex)
{
ServerLogs("AcceptCallback SocketException " + hostname + ex.Message.ToString());
}
}
I did search online about socket exeption programming but cant find anything related to this particular call stack and the process terminating.
I've been stock on this for a week ,I have no contact on the developer who made this.
Thank you in advance.

C# - Multithreaded TCP Server/Client

I am trying to understand the correct way of how should I make good multithreaded TCP server.
Here is what I have so far:
public class WorldServer
{
public List<ServerClient> clients = new List<ServerClient>();
public int port = 8080;
public TcpListener server;
private bool serverStarted;
private int connectionIncrementor;
private MySQLConnection mySQLConnection = new MySQLConnection();
private MySqlConnection mysqlConn = null;
static void Main(string[] args)
{
WorldServer serverInstance = new WorldServer();
Console.WriteLine("Starting World Server...");
try
{
serverInstance.mysqlConn = new MySqlConnection(serverInstance.mySQLConnection.mysqlConnectionString);
serverInstance.mysqlConn.Open();
Console.WriteLine("Connected to MySQL version: " + serverInstance.mysqlConn.ServerVersion + "\n");
}
catch (Exception e)
{
Console.WriteLine("MySQL Error: " + e.ToString());
}
finally
{
if (serverInstance.mysqlConn != null)
{
serverInstance.mysqlConn.Close();
}
}
serverInstance.clients = new List<ServerClient>();
try
{
serverInstance.server = new TcpListener(IPAddress.Any, serverInstance.port);
serverInstance.server.Start();
serverInstance.StartListening();
serverInstance.serverStarted = true;
Console.WriteLine("Server has been started on port: " + serverInstance.port);
}
catch (Exception e)
{
Console.WriteLine("Socket error: " + e.Message);
}
while (true)
{
serverInstance.Update();
}
}
private void Update()
{
//Console.WriteLine("Call");
if (!serverStarted)
{
return;
}
foreach (ServerClient c in clients.ToList())
{
//Check if TCP is not null
if (c.tcp == null)
return;
// Is the client still connected?
if (!IsConnected(c.tcp))
{
c.tcp.Close();
clients.Remove(c);
Console.WriteLine(c.connectionId + " has disconnected.");
continue;
//Console.WriteLine("Check for connection?\n");
}
else
{
// Check for message from Client.
NetworkStream s = c.tcp.GetStream();
if (s.DataAvailable)
{
string data = c.streamReader.ReadLine();
if (data != null)
{
if (ValidateJSON(data))
{
Thread incomingData = new Thread(() => OnIncomingData(c, data));
incomingData.Start();
}
}
}
//continue;
}
}
}
public bool ValidateJSON(string s)
{
try
{
JToken.Parse(s);
return true;
}
catch (JsonReaderException ex)
{
Trace.WriteLine(ex);
return false;
}
}
private void OnIncomingData(ServerClient c, string data)
{
dynamic json = JsonConvert.DeserializeObject(data);
string header = json.header;
//Console.WriteLine("HEADER ID:" + json.header);
string connId = json.connectionId;
int.TryParse(connId, out int connectionId);
int characterId = 0;
Dictionary<string, string> receivedData = new Dictionary<string, string>();
if (json.data != null)
{
receivedData = json.data.ToObject<Dictionary<string, string>>();
}
if (json.data["characterId"] != null)
{
characterId = json.data["characterId"];
}
string prefix = header.Substring(0, 2);
if (prefix != "1x")
{
Console.WriteLine("Unknown packet: " + data + "\n");
}
else
{
string HeaderPacket = header.Substring(2);
switch (HeaderPacket)
{
default:
Console.WriteLine("Unknown packet: " + data + "\n");
break;
case "004":
Console.WriteLine("Test Packet"); ;
break;
}
}
//Broadcast(null, data, clients);
//Console.WriteLine(c.clientName + " has sent the following message :" + data);
}
public bool IsConnected(TcpClient c)
{
try
{
if (c != null && c.Client != null && c.Client.Connected)
{
if (c.Client.Poll(0, SelectMode.SelectRead))
{
return !(c.Client.Receive(new byte[1], SocketFlags.Peek) == 0);
}
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
private void StartListening()
{
server.BeginAcceptTcpClient(OnConnection, server);
}
private void OnConnection(IAsyncResult ar)
{
connectionIncrementor++;
TcpListener listener = (TcpListener)ar.AsyncState;
clients.Add(new ServerClient(listener.EndAcceptTcpClient(ar)));
clients[clients.Count - 1].connectionId = connectionIncrementor;
StartListening();
//Send a message to everyone, say someone has connected!
Dictionary<string, object> SendDataBroadcast = new Dictionary<string, object>();
SendDataBroadcast.Add("connectionId", clients[clients.Count - 1].connectionId);
Broadcast("001", SendDataBroadcast, clients[clients.Count - 1].connectionId);
Console.WriteLine(clients[clients.Count - 1].connectionId + " has connected.");
}
public void Broadcast(string header, Dictionary<string, object> data, int cnnId = 0)
{
string jsonData = JsonConvert.SerializeObject(data, Formatting.Indented);
foreach (ServerClient c in clients)
{
try
{
if (header == null)
{
header = "000";
}
JsonData SendData = new JsonData();
SendData.header = "0x" + header;
SendData.data = JObject.Parse(jsonData);
SendData.connectionId = cnnId;
string JSonData = JsonConvert.SerializeObject(SendData);
//Console.WriteLine("SENDING: " + JSonData);
c.streamWriter.WriteLine(JSonData);
c.streamWriter.Flush();
}
catch (Exception e)
{
Console.WriteLine("Write error : " + e.Message + " to client " + c.connectionId);
}
}
}
public void Send(string header, Dictionary<string, object> data, int cnnId)
{
string jsonData = JsonConvert.SerializeObject(data, Formatting.Indented);
foreach (ServerClient c in clients.ToList())
{
if (c.connectionId == cnnId)
{
try
{
//Console.WriteLine("Sending...");
if (header == null)
{
header = "000";
}
JsonData SendData = new JsonData();
SendData.header = "0x" + header;
SendData.data = JObject.Parse(jsonData);
SendData.connectionId = cnnId;
string JSonData = JsonConvert.SerializeObject(SendData);
c.streamWriter.WriteLine(JSonData);
c.streamWriter.Flush();
//Console.WriteLine("Trying to send data to connection id: " + cnnId + " data:" + sendData);
}
catch (Exception e)
{
Console.WriteLine("Write error : " + e.Message + " to client " + c.connectionId);
}
}
}
}
}
public class ServerClient
{
public TcpClient tcp;
public StreamReader streamReader;
public StreamWriter streamWriter;
public int accountId;
public int connectionId;
public ServerClient(TcpClient clientSocket)
{
tcp = clientSocket;
streamReader = new StreamReader(tcp.GetStream(), false);
streamWriter = new StreamWriter(tcp.GetStream());
clientSocket.NoDelay = true;
}
}
The TCP server works. However I am really not sure if this is the best approach I can take.
Have I made the multi-threading well ? Probably not. I would like to receive advices where i can make it better.
Do I need to create a new thread on every OnIncomingData ?
Do I need to create new thread on every Send and Broadcast ?
Very often I receive error here foreach (ServerClient c in clients.ToList()). What can be the cause of it ?
What parts of the client is good to be multithreaded also aka the listening function for incoming data or the sending functions?
All advices are most welcome!
I wrote code for an OP last year that was a TCP Server and wrote to a SQL Server. I modified that code a few minutes ago to make it more general. The changes are not tested but original code worked very well. I used Asynchronous Send and Receive. I also used a fifo to send messages from the transport layer to the application layer. See code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Data;
using System.Data.SqlClient;
using System.Timers;
using System.Threading;
namespace TCP_Server
{
public class StateObject
{
public long connectionNumber = -1;
public Socket workSocket { get; set; }
public byte[] buffer { get; set; }
public int fifoCount { get; set; }
}
public enum PROCESS_STATE
{
ACCEPT,
READ,
PROCESS,
UNPACK
}
public enum UNPACK_STATUS
{
ERROR,
NOT_ENOUGH_BYTES,
BAD_CRC,
GOOD_MESSAGE,
DEFAULT
}
public enum PROTOCOL_NUMBER
{
LOGIN_MESSAGE,
NONE
}
class Program
{
const string IP = "127.0.0.1";
const int PORT = 8841;
const Boolean test = true;
static void Main(string[] args)
{
Server server = new Server(IP, PORT, test);
Console.WriteLine("Connection Ended");
}
}
public class Server
{
const int BUFFER_SIZE = 1024;
const string CONNECT_STRING = #"Data Source=.\SQLEXPRESS;Initial Catalog=MyDataTable;Integrated Security=SSPI;";
const string LOGIN_INSERT_COMMMAND_TEXT = "use MyTable INSERT INTO Login (TerminalID,Date) VALUES(#TerminalID,#Date)";
const string LOCATION_INSERT_COMMMAND_TEXT = "INSERT INTO MyTable (CurrTime, Message)" +
"VALUES (#CurrTime, #Message)";
static SqlConnection conn = null;
static SqlCommand cmdLogin = null;
static SqlCommand cmdLocation = null;
static long connectionNumber = 0;
//mapping of connection number to StateObject
static Dictionary<long, KeyValuePair<List<byte>, StateObject>> connectionDict = new Dictionary<long, KeyValuePair<List<byte>, StateObject>>();
//fifo contains list of connections number wait with receive data
public static List<long> fifo = new List<long>();
public static AutoResetEvent allDone = new AutoResetEvent(false);
public static AutoResetEvent acceptDone = new AutoResetEvent(false);
public enum DATABASE_MESSAGE_TYPE
{
LOGIN,
LOCATION
}
public class WriteDBMessage
{
public DATABASE_MESSAGE_TYPE message { get; set; }
}
public class WriteDBMessageLogin : WriteDBMessage
{
public DateTime date { get; set; }
public string message { get; set; }
}
public class WriteDBMessageLocation : WriteDBMessage
{
public DateTime currTime { get; set; }
public byte[] message { get; set; }
}
public static class WriteDBAsync
{
public enum Mode
{
READ,
WRITE
}
public static List<WriteDBMessage> fifo = new List<WriteDBMessage>();
public static System.Timers.Timer timer = null;
public static void WriteDatabase()
{
timer = new System.Timers.Timer(1000);
timer.Elapsed += Timer_Elapsed;
timer.Start();
}
public static WriteDBMessage ReadWriteFifo(Mode mode, WriteDBMessage message)
{
Object thisLock2 = new Object();
lock (thisLock2)
{
switch (mode)
{
case Mode.READ:
if (fifo.Count > 0)
{
message = fifo[0];
fifo.RemoveAt(0);
}
break;
case Mode.WRITE:
fifo.Add(message);
break;
}
}
return message;
}
static void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
timer.Enabled = false;
WriteDBMessage row = null;
int rowsAdded = 0;
uint number = 0;
try
{
while ((row = ReadWriteFifo(Mode.READ, null)) != null)
{
switch (row.message)
{
case DATABASE_MESSAGE_TYPE.LOGIN:
cmdLogin.Parameters["#Date"].Value = ((WriteDBMessageLogin)row).date;
rowsAdded = cmdLogin.ExecuteNonQuery();
break;
}
}
}
catch (Exception ex)
{
//Console.WriteLine("Error : '{0}'", ex.Message);
}
timer.Enabled = true;
}
}
public Server(string IP, int port, Boolean test)
{
try
{
conn = new SqlConnection(CONNECT_STRING);
conn.Open();
cmdLogin = new SqlCommand(LOGIN_INSERT_COMMMAND_TEXT, conn);
cmdLogin.Parameters.Add("#TerminalID", SqlDbType.NVarChar, 8);
cmdLogin.Parameters.Add("#Date", SqlDbType.DateTime);
cmdLocation = new SqlCommand(LOCATION_INSERT_COMMMAND_TEXT, conn);
cmdLocation.Parameters.Add("#IMEI", SqlDbType.NVarChar, 50);
cmdLocation.Parameters.Add("#TrackTime", SqlDbType.DateTime);
cmdLocation.Parameters.Add("#currTime", SqlDbType.DateTime);
cmdLocation.Parameters.Add("#Longitude", SqlDbType.NChar, 50);
cmdLocation.Parameters.Add("#Lattitude", SqlDbType.NVarChar, 50);
cmdLocation.Parameters.Add("#speed", SqlDbType.Float);
}
catch (Exception ex)
{
Console.WriteLine("Error : '{0}'", ex.Message);
//Console.ReadLine();
return;
}
try
{
//initialize the timer for writing to database.
WriteDBAsync.WriteDatabase();
StartListening(IP, port, test);
// Open 2nd listener to simulate two devices, Only for testing
//StartListening(IP, port + 1, test);
ProcessMessages();
}
catch (Exception ex)
{
Console.WriteLine("Error : '{0}'", ex.Message);
//Console.ReadLine();
return;
}
}
public void StartListening(string IP, int port, Boolean test)
{
try
{
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.GetHostEntry(IP); //Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
//IPAddress local = IPAddress.Parse(IP);
IPEndPoint localEndPoint = null;
if (test)
{
localEndPoint = new IPEndPoint(IPAddress.Any, port);
}
else
{
localEndPoint = new IPEndPoint(ipAddress, port);
}
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
allDone.Reset();
acceptDone.Reset();
listener.Bind(localEndPoint);
listener.Listen(100);
//login code, wait for 1st message
Console.WriteLine("Wait 5 seconds for login message");
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
public void ProcessMessages()
{
UInt16 sendCRC = 0;
DateTime date;
int year = 0;
int month = 0;
int day = 0;
int hour = 0;
int minute = 0;
int second = 0;
KeyValuePair<List<byte>, StateObject> byteState;
KeyValuePair<UNPACK_STATUS, byte[]> status;
byte[] receiveMessage = null;
StateObject state = null;
byte[] serialNumber = null;
byte[] serverFlagBit = null;
byte[] stringArray = null;
string stringMessage = "";
byte lengthOfCommand = 0;
PROTOCOL_NUMBER protocolNumber = PROTOCOL_NUMBER.NONE;
try
{
Boolean firstMessage = true;
acceptDone.Set();
//loop forever
while (true)
{
allDone.WaitOne();
//read fifo until empty
while (true)
{
//read one connection until buffer doesn't contain any more packets
byteState = ReadWrite(PROCESS_STATE.PROCESS, null, null, -1);
if (byteState.Value.fifoCount == -1) break;
state = byteState.Value;
while (true)
{
status = Unpack(byteState);
if (status.Key == UNPACK_STATUS.NOT_ENOUGH_BYTES)
break;
if (status.Key == UNPACK_STATUS.ERROR)
{
Console.WriteLine("Error : Bad Receive Message, Data");
break;
}
//message is 2 start bytes + 1 byte (message length) + 1 byte message length + 2 end bytes
receiveMessage = status.Value;
int messageLength = receiveMessage[2];
Console.WriteLine("Status : '{0}', Receive Message : '{1}'", status.Key == UNPACK_STATUS.GOOD_MESSAGE ? "Good" : "Bad", BytesToString(receiveMessage.Take(messageLength + 5).ToArray()));
if (status.Key != UNPACK_STATUS.GOOD_MESSAGE)
{
break;
}
else
{
if (firstMessage)
{
if (receiveMessage[3] != 0x01)
{
Console.WriteLine("Error : Expected Login Message : '{0}'", BytesToString(receiveMessage));
break;
}
firstMessage = false;
}
//skip start bytes, message length. then go back 4 bytes (CRC and serial number)
serialNumber = receiveMessage.Skip(2 + 1 + messageLength - 4).Take(2).ToArray();
protocolNumber = (PROTOCOL_NUMBER)receiveMessage[3];
Console.WriteLine("Protocol Number : '{0}'", protocolNumber.ToString());
switch (protocolNumber)
{
case PROTOCOL_NUMBER.LOGIN_MESSAGE:
break;
} //end switch
}// End if
} //end while
}//end while fifo > 0
allDone.Reset();
}//end while true
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
static string BytesToString(byte[] bytes)
{
return string.Join("", bytes.Select(x => x.ToString("X2")));
}
static KeyValuePair<UNPACK_STATUS, byte[]> Unpack(KeyValuePair<List<byte>, StateObject> bitState)
{
List<byte> working_buffer = bitState.Key;
//return null indicates an error
if (working_buffer.Count() < 3) return new KeyValuePair<UNPACK_STATUS, byte[]>(UNPACK_STATUS.NOT_ENOUGH_BYTES, null);
int len = working_buffer[2];
if (working_buffer.Count < len + 5) return new KeyValuePair<UNPACK_STATUS, byte[]>(UNPACK_STATUS.NOT_ENOUGH_BYTES, null);
// check start and end bytes
// remove message fro workig buffer and dictionary
KeyValuePair<List<byte>, StateObject> byteState = ReadWrite(PROCESS_STATE.UNPACK, null, null, bitState.Value.connectionNumber);
if (byteState.Key.Count == 0) return new KeyValuePair<UNPACK_STATUS, byte[]>(UNPACK_STATUS.ERROR, null);
List<byte> packet = byteState.Key;
//crc test
byte[] crc = packet.Skip(len + 1).Take(2).ToArray();
ushort crcShort = (ushort)((crc[0] << 8) | crc[1]);
//skip start bytes, crc, and end bytes
return new KeyValuePair<UNPACK_STATUS, byte[]>(UNPACK_STATUS.GOOD_MESSAGE, packet.ToArray());
}
static KeyValuePair<List<byte>, StateObject> ReadWrite(PROCESS_STATE ps, Socket handler, IAsyncResult ar, long unpackConnectionNumber)
{
KeyValuePair<List<byte>, StateObject> byteState = new KeyValuePair<List<byte>, StateObject>(); ;
StateObject stateObject = null;
int bytesRead = -1;
int workingBufferLen = 0;
List<byte> working_buffer = null;
byte[] buffer = null;
Object thisLock1 = new Object();
lock (thisLock1)
{
switch (ps)
{
case PROCESS_STATE.ACCEPT:
acceptDone.WaitOne();
acceptDone.Reset();
stateObject = new StateObject();
stateObject.buffer = new byte[BUFFER_SIZE];
connectionDict.Add(connectionNumber, new KeyValuePair<List<byte>, StateObject>(new List<byte>(), stateObject));
stateObject.connectionNumber = connectionNumber++;
stateObject.workSocket = handler;
byteState = new KeyValuePair<List<byte>, StateObject>(null, stateObject);
acceptDone.Set();
break;
case PROCESS_STATE.READ:
//catch when client disconnects
//wait if accept is being called
//acceptDone.WaitOne();
try
{
stateObject = ar.AsyncState as StateObject;
// Read data from the client socket.
bytesRead = stateObject.workSocket.EndReceive(ar);
if (bytesRead > 0)
{
byteState = connectionDict[stateObject.connectionNumber];
buffer = new byte[bytesRead];
Array.Copy(byteState.Value.buffer, buffer, bytesRead);
byteState.Key.AddRange(buffer);
}
//only put one instance of connection number into fifo
if (!fifo.Contains(byteState.Value.connectionNumber))
{
fifo.Add(byteState.Value.connectionNumber);
}
}
catch (Exception ex)
{
//will get here if client disconnects
fifo.RemoveAll(x => x == byteState.Value.connectionNumber);
connectionDict.Remove(byteState.Value.connectionNumber);
byteState = new KeyValuePair<List<byte>, StateObject>(new List<byte>(), null);
}
break;
case PROCESS_STATE.PROCESS:
if (fifo.Count > 0)
{
//get message from working buffer
//unpack will later delete message
//remove connection number from fifo
// the list in the key in known as the working buffer
byteState = new KeyValuePair<List<byte>, StateObject>(connectionDict[fifo[0]].Key, connectionDict[fifo[0]].Value);
fifo.RemoveAt(0);
//put a valid value in fifoCount so -1 below can be detected.
byteState.Value.fifoCount = fifo.Count;
}
else
{
//getting here is normal when there is no more work to be performed
//set fifocount to zero so rest of code know fifo was empty so code waits for next receive message
byteState = new KeyValuePair<List<byte>, StateObject>(null, new StateObject() { fifoCount = -1 });
}
break;
case PROCESS_STATE.UNPACK:
try
{
working_buffer = connectionDict[unpackConnectionNumber].Key;
workingBufferLen = working_buffer[2];
if ((working_buffer[0] != 0x78) && (working_buffer[1] != 0x78) && (working_buffer[workingBufferLen + 3] != 0x0D) && (working_buffer[workingBufferLen + 4] != 0x0A))
{
working_buffer.Clear();
return new KeyValuePair<List<byte>, StateObject>(new List<byte>(), null);
}
List<byte> packet = working_buffer.GetRange(0, workingBufferLen + 5);
working_buffer.RemoveRange(0, workingBufferLen + 5);
byteState = new KeyValuePair<List<byte>, StateObject>(packet, null);
}
catch (Exception ex)
{
int testPoint = 0;
}
break;
}// end switch
}
return byteState;
}
public static void AcceptCallback(IAsyncResult ar)
{
try
{
// Get the socket that handles the client request.
// Retrieve the state object and the handler socket
// from the asynchronous state object.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = ReadWrite(PROCESS_STATE.ACCEPT, handler, ar, -1).Value;
handler.BeginReceive(state.buffer, 0, BUFFER_SIZE, 0,
new AsyncCallback(ReadCallback), state);
}
catch (Exception ex)
{
int myerror = -1;
}
}
public static void ReadCallback(IAsyncResult ar)
{
try
{
StateObject state = ar.AsyncState as StateObject;
Socket handler = state.workSocket;
// Read data from the client socket.
KeyValuePair<List<byte>, StateObject> byteState = ReadWrite(PROCESS_STATE.READ, handler, ar, -1);
if (byteState.Value != null)
{
allDone.Set();
handler.BeginReceive(state.buffer, 0, BUFFER_SIZE, 0,
new AsyncCallback(ReadCallback), state);
}
else
{
int testPoint = 0;
}
}
catch (Exception ex)
{
int myerror = -1;
}
// Signal the main thread to continue.
allDone.Set();
}
}
}

C#, tcpClient to Multiple IP Address but on the same port

Scenario:
I have multiple machines, each wit hit's own IP, that run a tcpServer, all on the same port. During each transaction data is sent if the tcpServer port is opened. It, looks for a client before opening the port.
What I Need:
I'm writing an app, that needs to:
1. Check through the list of IP's if they are availible
2. Open a tcpClient port to each machine IP, (all on the same ports)
3. After every specified time make sure the connection is open, if not reopen connection.
Future:
I use an XMl file to give the SQL data which is used to get the list of machines and the port to listen on. In this xml is a udp setting as well, if this is yes, then the data being sent, must be received and redirected to a specified UDP port.
The Class:
public static void tcpListen(IPAddress server, int port)
{
try
{
TcpListener listener = new TcpListener(server, port);
listener.AcceptTcpClient();
listener.Start();
while (true)
{
Socket client = listener.AcceptSocket();
var childSocketThread = new Thread(() =>
{
byte[] data = new byte[100];
int size = client.Receive(data);
for (int i = 0; i < size; i++)
feedback = server + ":" + port + ": " + Convert.ToChar(data[i]);
using (StreamWriter w = File.AppendText("TCPLog.log"))
{
Log(feedback, w);
}
client.Close();
});
childSocketThread.Start();
}
}
catch (Exception err)
{
using (StreamWriter w = File.AppendText("error.log"))
{
Log("tcpControl.tcpListen: " + err.Message, w);
}
}
}
The part of the code that repeats every few seconds:
private void ptoCheck()
{
IPAddress sourceIP;
int sourcePort;
int destinationPort;
string tcpStatus;
int oldCOunt = dgvWorkstations.RowCount;
int newCount = sqlScripts.posCount(sqlServer, sqlUser, sqlPassword, sqlDatabase);
if (newCount != oldCOunt)
{
getWorkstations();
}
try
{
foreach (DataGridViewRow row in dgvWorkstations.Rows)
{
int i = row.Index;
bool tcpState;
dgvWorkstations["Status", i].Value = "Checking";
dgvWorkstations.Refresh();
name = row.Cells["POS_Name"].Value.ToString();
sourceIP = IPAddress.Parse(row.Cells["LastKnownIP"].Value.ToString());
sourcePort = Convert.ToInt32(row.Cells["Receive_Port"].Value.ToString());
destinationPort = Convert.ToInt32(row.Cells["Send_Port"].Value.ToString());
tcpState = tcpControl.tcpCheck(sourceIP, sourcePort, name);
if (tcpState == false)
{
dgvWorkstations["Status", i].Value = "Connecting";
dgvWorkstations.Refresh();
tcpStatus = tcpControl.tcpConnect(sourceIP, sourcePort, name);
tcpControl.tcpListen(sourceIP, sourcePort);
dgvWorkstations["Status", i].Value = tcpStatus;
}
if (tcpState == true)
{
dgvWorkstations["Status", i].Value = "Connected";
dgvWorkstations.Refresh();
}
i = i + 1;
}
}
catch (Exception err)
{
using (StreamWriter w = File.AppendText("AError.log"))
{
Log("frmMain.ptoCheck: (" + name + ") " + err.Message, w);
}
}//End Catch
}
I got the following code toe work, from my class I can now make multiple connections, however. The part where I call another method to listen and receive the data blocks the first method and holds it untill the connection drops without making further connections.
My Class:
public void tcpTest2(IPAddress server, Int32 port, int x)
{
TcpClient client;
sendData("Connecting to Host: " + server + " on port: " + port.ToString() + "...");
sendStatus("Connecting", x);
try
{
client = new TcpClient(server.ToString(), port);
if (false)
{
}
if (true)
{
sendData("Connection to Host: " + server + " on port: " + port.ToString() + "..ESTABLISHED");
sendStatus("Connected", x);
receiveData(client, server, port);
}
}
catch (Exception)
{
sendData("Connection to Host: " + server + " on port: " + port.ToString() + "..FAILED");
sendStatus("Failed", x);
}
}
public void receiveData(TcpClient client, IPAddress server, int port)
{
Byte[] data = System.Text.Encoding.Default.GetBytes("|");
data = new byte[1024];
string stringData;
bool connected;
connected = true;
while (connected == true)
{
string fromC = client.Client.RemoteEndPoint.ToString();
NetworkStream ns = client.GetStream();
int recv = ns.Read(data, 0, data.Length);
stringData = Encoding.ASCII.GetString(data, 0, recv);
sendUpdate("{" + fromC + "}" + stringData);
connected = IsConnected(client);
}
if (connected == false)
{
sendData("Connection to Host: " + server + " on port: " + port.ToString() + "..LOST");
sendLost(server);
}
}
public bool IsConnected(TcpClient client)
{
try
{
if (client != null && client.Client != null && client.Client.Connected)
{
if (client.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if (client.Client.Receive(buff, SocketFlags.Peek) == 0)
{
return false;
}
else
{
return true;
}
}
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
}
Here is the final code that worked for me:
My Class:
public void tcpConnect(object pos)
{
IPAddress hostIP = IPAddress.Parse(pos.ToString().Split(':')[0]);
int hostPort = Int32.Parse(pos.ToString().Split(':')[1]);
rowInd = Int32.Parse(pos.ToString().Split(':')[2]);
var client = new TcpClient();
if (!client.ConnectAsync(hostIP, hostPort).Wait(1000))
{
sendData("Connection to Host: " + hostIP + " on port: " + hostPort.ToString() + ".FAILED");
sendStatus("Failed", "", rowInd);
return;
}
if (true)
{
sendData("Connection to Host: " + hostIP.ToString() + " on port: " + hostPort.ToString() + "..ESTABLISHED");
Thread thread = new Thread(new ParameterizedThreadStart(ClientHandler));
thread.IsBackground = true;
Thread.FreeNamedDataSlot(hostIP.ToString() + rowInd.ToString());
thread.Name = hostIP.ToString() + rowInd.ToString();
thread.Start(client);
threadID = thread.ManagedThreadId.ToString();
sendStatus("Connected", threadID, rowInd);
}
}
public bool IsConnected(TcpClient client)
{
try
{
if (client != null && client.Client != null && client.Client.Connected)
{
if (client.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if (client.Client.Receive(buff, SocketFlags.Peek) == 0)
{
return false;
}
else
{
return true;
}
}
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
public void ClientHandler(object c)
{
TcpClient client = (TcpClient)c;
NetworkStream netstream = client.GetStream();
string fromC = client.Client.RemoteEndPoint.ToString();
string fromIP = fromC.Split(':')[0];
bool connected = true;
while (connected)
{
Thread.Sleep(10);
try
{
byte[] data = new byte[client.ReceiveBufferSize];
data = System.Text.Encoding.Default.GetBytes("|");
data = new byte[1024];
string stringData;
NetworkStream ns = client.GetStream();
int recv = ns.Read(data, 0, data.Length);
stringData = Encoding.ASCII.GetString(data, 0, recv);
sendUpdate("|" + fromC + "|" + stringData);
connected = IsConnected(client);
}
catch (Exception err)
{
connected = false;
sendLost(fromIP);
using (StreamWriter w = File.AppendText("Arch-PTO.log"))
{
Log("tcpServices.ClientHandler: " + err.Message, w);
}
}
}
sendLost(fromIP);
}

TCPListener Not Accepting Connection

I'm having an issue with a TCPListener. I have created this code below and it works with a test application, but I can't get it to receive the connection from the production box. In the image below you can see .44 is continuously attempting to connect, but as seen in the Console window output, no connection is ever received beyond the Listening Started.
What am I overlooking?
public class TCPServer
{
#region Privates
private ILog log;
private readonly string _connectionString = "";
private readonly List<AgentState> _lAgentState;
private readonly DateTime _lastUpdatedRecord = new DateTime();
private readonly TcpClient _tcpClient;
private readonly IPEndPoint _serverEndPoint;
private int _messageNumber = 2;
private TcpListener _tcpListener;
private Thread _listenThread;
#endregion
public IEXHermes()
{
var methodName = new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name;
try
{
log = LogManager.GetLogger("Logger");
log.Info("Class Starting");
_connectionString = Properties.Settings.Default.HN_ConnectionString;
_lAgentState = getInitialState();
_lastUpdatedRecord = _lAgentState.Max(w => w.actionLocalTime);
Int32 iexPort = Int32.Parse(Properties.Settings.Default.IEX_Port);
_tcpListener = new TcpListener(IPAddress.Any, iexPort);
log.Debug("Server Open on Server: " + IPAddress.Any);
log.Debug("Server Open on Port: " + iexPort);
_listenThread = new Thread(listenForClients);
_listenThread.Start();
}
catch (Exception ex)
{
log.FatalFormat("{0} - {1} \n {2}", methodName, ex.Message, ex.StackTrace);
}
}
private void listenForClients()
{
var methodName = new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name;
log.Debug(methodName + " Starting");
try
{
log.Debug(methodName + " - Listening Started");
_tcpListener.Start();
while (true)
{
try
{
var client = _tcpListener.AcceptSocket();
var clientThread = new Thread(handleClientComm);
clientThread.Start(client);
}
catch (Exception ex)
{
log.FatalFormat("{0} - {1} \n {2}", methodName, ex.Message, ex.StackTrace);
}
}
} catch (Exception ex)
{
log.FatalFormat("{0} - {1} \n {2}", methodName, ex.Message, ex.StackTrace);
}
log.Debug(methodName + ": Listener Closer");
}
private void handleClientComm(object client)
{
var methodName = new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name;
var tcpClient = (TcpClient)client;
log.Debug(methodName + ": New Connection Established");
try
{
var clientStream = tcpClient.GetStream();
var message = new byte[4096];
while (true)
{
var bytesRead = 0;
try
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
break;
}
if (bytesRead == 0)
{
break;
}
var encoder = new ASCIIEncoding();
var a = encoder.GetString(message, 0, bytesRead);
Console.WriteLine("Recieved: " + a.ToUpper());
if (a.ToUpper().Contains("INIT"))
{
a = sessionInitialize();
}
tcpClient.Client.Send(Encoding.UTF8.GetBytes(a));
Console.WriteLine("Sent: " + a);
}
}
catch (Exception ex)
{
log.FatalFormat("{0} - {1} \n {2}", methodName, ex.Message, ex.StackTrace);
}
finally
{
tcpClient.Close();
}
}
}
maybe try to replace IPAddress.Any by the real IP at least for testing purpose, just to be sure...

telnet connection to a c# socket doesn't close

I have a c# socket based server which serves TCP clients.
I use telnet based monitoring to see if the server is listening.
to versify clients are up i use server keep alive (sending a random string data), and if socket expection raises-i remove the client from a client's dictionary.
the probelm is: the telnet connections to the socket doesn't get removed from the list of connections and the number of clients is rising up slowly but surely.
i tried a telnet manually to the server through command line and than closing the telnet connection-nothing.the server just keep sending the keep alive to the telnet connection with no execptions.
this is my read call back:
protected void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the async state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.socket;
if (state.socket == null)
return;
if (!state.socket.Connected)
return;
int id = state.id;
try
{
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
string newAddedStr = string.Empty;
newAddedStr = Encoding.UTF8.GetString(state.buffer, 0, bytesRead);
//cut the new message and add it
if (state.sb == null)
state.sb = new StringBuilder();
state.sb.Append(newAddedStr);
// There might be more data, so store the data received so far.
//add data until end of XML
content = state.sb.ToString();
//IF GOT FULL MESSAGE FROM SOCKET
if ((content.Length > 0) /*&& (content.IndexOf("\0") > -1)*/)
{
String strh = String.Format("Client # {0} data: ", id);
strh += content.Replace("\0", "");
if (!strh.Contains("keepalive"))
LogWriter.Trace(strh, "");
// l(writeToGetTextBoxMsg), new object[] { strh });
if (state != null)
{
if (state.sb == null)
state.sb = new StringBuilder();
state.sb.Length = 0;
}
//add the rest of the xml
string objData = content.Replace("\0", "");
string xmlData = objData.ToString();
try
{
if (xmlData.Contains("Unsubscribe"))
{
RemoveSubscriber(xmlData);
}
else
{
if (xmlData.Contains("Subscribe"))
{
if (!state.IsInitiated)
{
state.Init();
state.socketClient.OnSocketError += new SocketErrorHandler(socketClient_OnSocketError);
state.socketClient.clientSocket = handler;
}
AddSubscriber(xmlData, state);
}
}
xmlData = null;
objData = null;
content = null;
}
catch (ArgumentOutOfRangeException ex)
{
LogWriter.Trace(newAddedStr,"ArgumentOutOfRangeException in ReadCallback");
}
catch (Exception ex)
{
LogWriter.TraceError(ex.Message + " " + ex.StackTrace + " " + newAddedStr);
}
#region oldCode
#endregion
}
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(this.ReadCallback), state);
}
}
catch (System.Net.Sockets.SocketException es)
{
closeSocket(state, false, "Execption:" + es.Message + "," + es.StackTrace);
if (es.ErrorCode != 64)
{
LogWriter.Trace(string.Format("Socket Exception: {0}, {1}.", es.ErrorCode, es.ToString()), "");
}
}
catch (Exception e)
{
closeSocket(state, false,"Execption:"+e.Message+","+e.StackTrace);
if (e.GetType().FullName != "System.ObjectDisposedException")
{
Console.WriteLine("Exception: " + e.StackTrace);
LogWriter.Trace("Exception Message: " + e.ToString() + e.StackTrace, "");
Console.WriteLine("Exception Message: " + e.ToString());
LogWriter.Trace("ReadCallback:" + e.Message + " " + e.StackTrace, "ERROR");
}
}
}
any ideas?
When you do a read of a socket and 0 is returned you know that the other side of the connection has closed. Are you doing that?

Categories