TCP server causes MAX CPU utlization - c#

i write this TCP communication library. the problem is that. when a client connects. the CPU usages boosts to maximum....this causes other application to become slow...
please take a look at the code and correct me where i did wrong..
the main code of my TCP library is
TCP Server Class
public class TCPServerEndPoint : ICommunication
{
private string channelName;
private string localIP;
private int localPort;
private string remoteIP;
private int remotePort;
private TcpListener tcpListenter;
/// <summary>
/// Accept the incomming connection and pass it to a thread to handle communication.
/// </summary>
private TCPServerWorker worker;
/// <summary>
/// List of threads created for connected clients.
/// </summary>
List<TCPServerWorker> workerThreads;
/// <summary>
/// Thread to keep listening process in seperate thread.
/// </summary>
private Thread serverThread;
/// <summary>
/// Flag to keep status of Endpoint.
/// </summary>
private bool keepRunning;
public TCPServerEndPoint()
{
this.keepRunning = false;
Guid guid = Guid.NewGuid();
channelName = guid.ToString();
workerThreads = new List<TCPServerWorker>();
}
public TCPServerEndPoint(string localIP, int localPort, string remoteIP, int remotePort)
{
this.localIP = localIP;
this.localPort = localPort;
this.remoteIP = remoteIP;
this.remotePort = remotePort;
workerThreads = new List<TCPServerWorker>();
this.keepRunning = false;
}
public event EventHandler<CommEventArgs> OnCommReceive;
public int CommStart()
{
if (this.IsStarted == true)
{
Console.WriteLine("TCP Server is already running");
return -1;
}
serverThread = new Thread(new ThreadStart(StartListening));
serverThread.IsBackground = true;
serverThread.Start();
return 0;
}
private void StartListening()
{
try
{
IPAddress localAddress = IPAddress.Parse(this.localIP);
tcpListenter = new TcpListener(localAddress, this.localPort);
tcpListenter.Start();
Console.WriteLine("TCP Server started");
Console.WriteLine("Server is listening on port : {0}", this.localPort);
this.keepRunning = true;
// look for incomming connections
while (this.keepRunning)
{
// connection received
TcpClient client = tcpListenter.AcceptTcpClient();
// create a new WorkerThread and pass the connected client to handle.
worker = new TCPServerWorker(client);
worker.dataReceived += new EventHandler<CommEventArgs>(worker_dataReceived);
workerThreads.Add(worker);
worker.Start();
}
tcpListenter.Stop();
Console.WriteLine("TCP Server stopped");
this.keepRunning = false;
}
catch
{
return;
}
}
void worker_dataReceived(object sender, CommEventArgs e)
{
if (this.OnCommReceive != null)
{
e.commChannel = this;
this.OnCommReceive(this, e);
}
}
public int CommStop()
{
if (this.IsStarted == false)
return -1;
// Close all worker threads created for connected clients.
foreach (TCPServerWorker item in workerThreads)
{
item.KeepRunning = false;
}
// break the listening loop
this.keepRunning = false;
// clear the worker thread list
workerThreads.Clear();
// force server to receive message to break while(keepRunning) loop
byte[] data = new byte[4];
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(this.localIP), localPort);
Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
tcpClient.Connect(ipEndPoint);
tcpClient.SendTo(data, ipEndPoint);
tcpClient.Close();
return 0;
}
public int CommSend(CommEventArgs obj)
{
obj.destAddress = this.remoteIP;
obj.destPort = this.remotePort;
return CommSendTo(obj);
}
public int CommSendTo(CommEventArgs obj)
{
int n;
byte[] buf;
try
{
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(obj.destAddress), obj.destPort);
buf = (byte[])obj.data;
Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
tcpClient.Connect(ipEndPoint);
n = tcpClient.SendTo(buf, ipEndPoint);
tcpClient.Close();
}
catch (Exception ex)
{
Console.WriteLine("Exception :: {0}", ex.Message);
return -1;
}
if (n == buf.Length)
{
if (OnCommSendComplete != null)
{
OnCommSendComplete(this, obj);
}
Console.WriteLine("Sent {0} bytes to {1}:{2}", n, obj.destAddress, obj.destPort);
}
else
{
return -1;
}
return n;
}
}
}
TCPServerWorker.cs
class TCPServerWorker
{
private TcpClient client;
private bool keepRunning;
public event EventHandler<CommEventArgs> dataReceived;
private const int MAX_TCP_DATA = 64000;
public bool KeepRunning
{
get
{
return this.keepRunning;
}
set
{
this.keepRunning = value;
}
}
public TCPServerWorker(TcpClient client)
{
this.client = client;
this.keepRunning = false;
}
public void Start()
{
Thread thread = new Thread(new ThreadStart(Process));
thread.IsBackground = true;
thread.Start();
}
private void Process()
{
if (client.Connected == true)
{
Console.WriteLine("Client connected :: {0}", client.Client.RemoteEndPoint);
this.keepRunning = true;
while (this.keepRunning)
{
// in my view. here is the main problem. this loop run for infinite time and causes CPU to reach at 100
byte[] buffer = new byte[MAX_TCP_DATA];
NetworkStream stream = client.GetStream();
StreamWriter writer = new StreamWriter(client.GetStream());
if (stream.DataAvailable == true)
{
int receivedBytesCount = stream.Read(buffer, 0, buffer.Length);
byte[] receivedBuffer = new byte[receivedBytesCount];
Array.Copy(buffer, receivedBuffer, receivedBytesCount);
String msg = Encoding.UTF8.GetString(receivedBuffer);
Console.WriteLine("Received MSG ::: " + msg);
writer.WriteLine("Server : Received {0} bytes", receivedBytesCount);
CommEventArgs comEventArg = new CommEventArgs();
comEventArg.data = (byte[])receivedBuffer;
IPEndPoint remoteIPEndPoint = (IPEndPoint)client.Client.RemoteEndPoint;
comEventArg.srcAddress = remoteIPEndPoint.Address.ToString();
comEventArg.srcPort = remoteIPEndPoint.Port;
comEventArg.length = receivedBytesCount;
this.OnDataReceived(comEventArg);
writer.Flush();
}
}
client.Close();
}
}
protected void OnDataReceived(CommEventArgs e)
{
if (this.dataReceived != null)
{
this.dataReceived(this, e);
}
}
}
}

You're using nonblocking I/O which leads to a loop (at least) in your client
while (this.keepRunning) {...}
which is consuming all your CPU resources by busy waiting.
You should consider to use blocking I/O or Socket.Select
Look at the first remark here
Details about select

One thing to note is that you never SET IsStarted .. you only GET it ._. Maybe you're spawning hundreds of threads =/ I'm talking about the TCPServerEndPoint class =/

Yes, you are busy waiting for a connection. I don't know socket programming so I can't give you details, but what you need to do is wait for a connection using the blocking system call.

I solved the issue after modifying the Process method of TCPServerWorker.cs
here is the changes
private void Process()
{
if (client.Connected == true)
{
Console.WriteLine("Client connected :: {0}", client.Client.RemoteEndPoint);
Byte[] bytes = new Byte[MAX_TCP_DATA];
String data = null;
NetworkStream stream = client.GetStream();
int i;
try
{
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// bytes contains received data in byte[].
// Translate data bytes to a UTF-8 string.
byte[] receivedBuffer = new byte[i];
Array.Copy(bytes, receivedBuffer, i);
data = System.Text.Encoding.UTF8.GetString(receivedBuffer);
Console.WriteLine("Received MSG ::: " + data);
// Process the data sent by the client.
byte[] msg = System.Text.Encoding.UTF8.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
CommEventArgs comEventArg = new CommEventArgs();
comEventArg.data = receivedBuffer;
IPEndPoint remoteIPEndPoint = (IPEndPoint)client.Client.RemoteEndPoint;
comEventArg.srcAddress = remoteIPEndPoint.Address.ToString();
comEventArg.srcPort = remoteIPEndPoint.Port;
comEventArg.length = i;
this.OnDataReceived(comEventArg);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception : " + ex.Message);
}
finally
{
client.Close();
}
}
}

Related

TcpClient connected but server not receiving message

Server :
public class TcpServer
{
private TcpListener tcpListener;
private static ManualResetEvent allDone = new ManualResetEvent(false);
public TcpServer(string url, int port)
{
tcpListener = new TcpListener(IPAddress.Parse(url), port);
pingMapper = new LightPingMapper();
}
public void Run()
{
tcpListener.Start();
Console.WriteLine("Server running");
while (true)
{
allDone.Reset();
tcpListener.BeginAcceptSocket(AcceptCallback, tcpListener);
Console.WriteLine("Accepting socket");
allDone.WaitOne();
}
Console.ReadLine();
}
private void AcceptCallback(IAsyncResult result)
{
try
{
allDone.Set();
var listener = (TcpListener) result.AsyncState;
var handler = listener.EndAcceptSocket(result);
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, state.buffer.Length, 0, ReadCallback, state);
}
catch (Exception e)
{
Console.WriteLine($"Error accepting callback. {e.Message}");
}
}
private void ReadCallback(IAsyncResult asyncResult)
{
try
{
string content = string.Empty;
Console.WriteLine("Read data from socket");
StateObject state = (StateObject) asyncResult.AsyncState;
Socket handler = state.workSocket;
int bytesRead = handler.EndReceive(asyncResult);
if (bytesRead > 0)
{
state.sb.Append(Encoding.UTF8.GetString(state.buffer));
content = state.sb.ToString();
Console.WriteLine(content + " " + DateTime.Now);
}
}
catch (Exception e)
{
Console.WriteLine($"Error reading socket. {e.Message}");
}
}
}
class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
Client:
public class TCPClientWrapper
{
private TcpClient tcpClient;
private readonly string address;
private readonly int port;
public TCPClientWrapper(string address, int port)
{
InitTcpClient();
this.address = address;
this.port = port;
}
public void SendMessage()
{
for(int i=0; i < 10; i++)
{
if (!SocketConnected())
{
TryConnect();
}
byte[] buffer = Encoding.UTF8.GetBytes("Hello");
tcpClient.Client.Send(buffer);
Thread.Sleep(60000);
}
}
private void TryConnect()
{
bool isConnected = false;
while (true)
{
try
{
InitTcpClient();
tcpClient.Connect(IPAddress.Parse(address), port);
if (SocketConnected())
{
Console.WriteLine("TcpClient, Connected");
isConnected = true;
break;
}
}
catch (Exception e)
{
Console.WriteLine("TcpClient, connection failed. Try to reconnect after 30 seconds, {0}", e.Message);
}
finally
{
if (!isConnected)
{
tcpClient.Close();
Thread.Sleep(30000);
}
}
}
}
private void InitTcpClient()
{
tcpClient = new TcpClient();
tcpClient.SendTimeout = 15;
}
private bool SocketConnected()
{
var s = tcpClient.Client;
if (!s.Connected)
return false;
bool part1 = s.Poll(1000, SelectMode.SelectRead);
bool part2 = s.Available == 0;
return !(part1 && part2);
}
}
The problem is that server read only first message , each next message is not received by server . The tcpClient is connected , but server doesn't receive any message . Could anyone suggest what is wrong with my code ?
In ReadCallback, you don't start the next read - so yes, your code only reads once.
Adding
handler.BeginReceive(state.buffer, 0, state.buffer.Length, 0, ReadCallback, state);
to the bottom of ReadCallback (when bytesRead > 0) should work. However! You aren't implementing proper framing, so you should be very cautious of that. A basic framing implementation for a text-based protocol (like this) would be to use some kind of line-end sentinel, and buffer data until you see a line-end, then process the line.
On TCP, you are only guaranteed to get the right bytes in the right order (or a failed socket eventually) - you are not guaranteed to get them in the same composition in terms of calls to Send exactly matching calls to Receive in terms of the numbers of bytes in each.

TCP Listener - Not updating a received data

This is my first TCP listener program,
I could receive, parse and display data successfully from another PC.
But can you please check why this listener is not receiving another data ?
I want to update it everytime time when a client sends data. But its not updating once received data.
Here is my code:
public partial class FeederControlMonitor : Form
{
public string Status = string.Empty;
public Thread T = null;
public FeederControlMonitor()
{
InitializeComponent();
}
private void FeederControlMonitor_Load(object sender, EventArgs e)
{
label1.Text = "Server is Running...";
ThreadStart Ts = new ThreadStart(StartReceiving);
T = new Thread(Ts);
T.Start();
}
public void StartReceiving()
{
ReceiveTCP(9100);
}
public void ReceiveTCP(int portN)
{
TcpListener Listener = null;
try
{
Listener = new TcpListener(IPAddress.Any, portN);
Listener.Start();
}
catch (Exception ex)
{
File.WriteAllText(#"C:\\Drive\\ex.txt", ex.Message);
Console.WriteLine(ex.Message);
}
try
{
Socket client = Listener.AcceptSocket();
byte[] data = new byte[10000];
int size = client.Receive(data);
while (true)
{
client.Close();
ParseData(System.Text.Encoding.Default.GetString(data));
}
Listener.Stop();
}
catch (Exception ex)
{
File.WriteAllText(#"C:\\Drive\\ex.txt", ex.Message);
}
}
public void ParseData(string data)
{
var useFulData = data.Substring(data.IndexOf("F1")).Replace(" ", "");
useFulData = useFulData.Remove(useFulData.IndexOf("<ETX>"));
string[] delimeters = { "<DEL>", "<ESC>" };
var listOfValues = useFulData.Split(delimeters, StringSplitOptions.None).ToList();
int pos = 0;
for (int i = 1; i < listOfValues.Count; i += 2, pos++)
{
listOfValues[pos] = listOfValues[i];
}
listOfValues.RemoveRange(pos, listOfValues.Count - pos);
txtTubeName.Text = listOfValues[0];
txtCID.Text = listOfValues[1];
txtLocation.Text = listOfValues[2];
txtGender.Text = listOfValues[3];
txtAge.Text = listOfValues[4];
}
private void btnExit_Click(object sender, EventArgs e)
{
T.Abort();
this.Close();
}
}
Thanks in advance.
To much to explain where are errors. Here is simple multithread TcpServer.
// Initialize listener.
IPAddress address = new IPAddress(new byte[] { 127, 0, 0, 1 });
TcpClient client;
// Bind to address and port.
TcpListener listener = new TcpListener(address, 12345);
// Start listener.
listener.Start();
// In endless cycle accepting incoming connections.
// Actually here must be something like while(_keepWork)
// and on some button code to make _keepWork = false to
// stop listening.
while (true)
{
client = listener.AcceptTcpClient();
// When client connected, starting BgWorker
// use "using" statement to automatically free objects after work.
using (BackgroundWorker bgWorker = new BackgroundWorker())
{
// EventHandler.
bgWorker.DoWork += BgWorker_DoWork;
// Past client as argument.
bgWorker.RunWorkerAsync(client);
}
}
And method to handle connection (Edit: with read data part):
private static void BgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Get argument as TcpClient.
TcpClient client = e.Argument as TcpClient;
// Get stream from client.
NetworkStream netStream = client.GetStream();
// Input buffer to read from stream.
int inBuffSize = 1024;
byte[] inBuff = new byte[inBuffSize];
// Temporary buffer.
byte[] tempBuff;
// Result data recieved from client.
List<byte> data = new List<byte>();
// Read bytes from client into inputbuffer
int dataSize = netStream.Read(inBuff, 0, inBuffSize);
// If data recieved add to result.
while (dataSize > 0)
{
// Create new buffer.
tempBuff = new byte[dataSize];
// Copy data from inputBuffer to tempBuffer.
Array.Copy(inBuff, tempBuff, dataSize);
// Add to result.
data.AddRange(tempBuff);
// Read once more to check if any data still could be recieved.
dataSize = netStream.Read(inBuff, 0, inBuffSize);
}
}

Tcp client send command toTcp Server to start x.exe and later server ignores client

I have created server and client everything worked just fine until I made 1 change. Created command start x.exe.
if(flag = Textmessage.ToLower() == "x.exe") //command from client
{
ProcessStartInfo _processStartInfo = new ProcessStartInfo();
_processStartInfo.WorkingDirectory = #"C:\Users\audrius\OneDrive\Programavimas\x\Bin\Debug\";
_processStartInfo.FileName = #"x.exe";
Process myProcess = Process.Start(_processStartInfo);
byte[] bytes = Encoding.ASCII.GetBytes("exe started");
socket.Send(bytes);//TELL client program started
ServerLogs.ServerLog("exe started");
Console.WriteLine("exe started");
return;
}
Everything works fine, I get response from server that program started. BUT then I want to send next command server don't accept it. Only then I restart client, server accept commands again. Why server freezes with this client?
My Client code:
namespace Multi_Client
{
class Program
{
private static readonly Socket _clientSocket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private const int _PORT = 100;
static string name = "Client";
static void Main()
{
Console.WriteLine("Welcome {0}", name);
Console.Title = "Client";
ConnectToServer();
RequestLoop();
Exit();
}
private static void ConnectToServer()
{
int attempts = 0;
while (!_clientSocket.Connected)
{
try
{
attempts++;
Console.WriteLine("Connection attempt " + attempts);
_clientSocket.Connect(IPAddress.Loopback, _PORT);
}
catch (SocketException)
{
Console.SetCursorPosition(0, Console.CursorTop - 1);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, Console.CursorTop - 1);
}
}
// Console.Clear();
Console.WriteLine("Connected");
}
private static void RequestLoop()
{
Console.WriteLine(#"<Type ""exit"" to properly disconnect client>");
while (true)
{
SendRequest();
ReceiveResponse();
}
}
/// <summary>
/// Close socket and exit app
/// </summary>
private static void Exit()
{
SendString(name+ "exit"); // Tell the server we re exiting
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
System.Threading.Thread.Sleep(1000);
Environment.Exit(0);
}
private static void SendRequest()
{
Console.Write("Send a request: ");
string request = name + " "+ Console.ReadLine();
SendString(request);
System.Threading.Thread.Sleep(1000);
if (request.ToLower() == name +" exit")
{
Exit();
}
}
/// <summary>
/// Sends a string to the server with ASCII encoding
/// </summary>
private static void SendString(string text)
{
byte[] buffer = Encoding.ASCII.GetBytes(text);
_clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
}
private static void ReceiveResponse()
{
if (_clientSocket.Connected)
{
var buffer = new byte[2048];
int received = _clientSocket.Receive(buffer, SocketFlags.None);
if (received == 0) return;
var data = new byte[received];
Array.Copy(buffer, data, received);
string text = Encoding.ASCII.GetString(data);
Console.WriteLine(text);
}
}
}
}
MY Server:
namespace Multi_Server
{
internal class Program
{
private static Socket _serverSocket;
private static readonly List<Socket> _clientSockets = new List<Socket> ();
private const int _BUFFER_SIZE = 2048;
private const int _PORT = 100;
private static readonly byte[] _buffer = new byte[1024];
private static void Main()
{
Console.Title = "Server";
Program.SetupServer();
Console.ReadLine();
Program.CloseAllSockets();
}
private static void SetupServer()
{
ServerLogs.ServerLog("Setting up server...");
Console.WriteLine("Setting up server...");
Program._serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Program._serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100));
Program._serverSocket.Listen(5);
Program._serverSocket.BeginAccept(new AsyncCallback(Program.AcceptCallback), null);
Console.WriteLine("Server setup complete");
ServerLogs.ServerLog("Server setup complete");
}
private static void CloseAllSockets()
{
foreach (Socket socket in _clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
_serverSocket.Close();
}
private static void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = _serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException)
{
return;
}
Program._clientSockets.Add(socket);
socket.BeginReceive(Program._buffer, 0, 1024, SocketFlags.None, new AsyncCallback(Program.ReceiveCallback), socket);
Console.WriteLine("Client connected, waiting for request...");
ServerLogs.ServerLog("Client connected, waiting for request...");
_serverSocket.BeginAccept(AcceptCallback, null);
}
private static void ReceiveCallback(IAsyncResult AR)
{
Socket socket = (Socket)AR.AsyncState;
int num;
try
{
num = socket.EndReceive(AR);
}
catch (SocketException)
{
Console.WriteLine("Client forcefully disconnected");
ServerLogs.ServerLog("Client forcefully disconnected");
socket.Close();
_clientSockets.Remove(socket);
return;
}
byte[] array = new byte[num];
Array.Copy(_buffer, array, num);
string RawText = Encoding.ASCII.GetString(array);
char[] textarray = RawText.ToCharArray();
int i = 0;
string name = "";
while (textarray[i] != ' ')
{
name += textarray[i];
i++;
}
string Textmessage = RawText.Substring(++i);
ServerLogs.ServerLog("Received from " + name + " !> Text: " + Textmessage);
Console.WriteLine("Received from {0} !> Text: {1}", name, Textmessage);
bool flag;
if(flag = Textmessage.ToLower() == "get time")
{
Console.WriteLine("Text is a get time request");
ServerLogs.ServerLog("Text is a get time request");
byte[] bytes = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
socket.Send(bytes);
ServerLogs.ServerLog("Time sent to client");
Console.WriteLine("Time sent to client");
}
else if(flag = Textmessage.ToLower() == "exit")
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
_clientSockets.Remove(socket);
ServerLogs.ServerLog("Client disconnected");
Console.WriteLine("Client disconnected");
return;
}
else if(flag = Textmessage.ToLower() == "x.exe") //command from client
{
ProcessStartInfo _processStartInfo = new ProcessStartInfo();
_processStartInfo.WorkingDirectory = #"C:\Users\audrius\OneDrive\Programavimas C#\Steambot Scrapper\Bin\Debug\";
_processStartInfo.FileName = #"x.exe";
Process myProcess = Process.Start(_processStartInfo);
byte[] bytes = Encoding.ASCII.GetBytes("exe started");
socket.Send(bytes);
ServerLogs.ServerLog("exe started");
Console.WriteLine("exe started");
return;
}
else
{
ServerLogs.ServerLog("Text is an invalid request");
Console.WriteLine("Text is an invalid request");
byte[] bytes = Encoding.ASCII.GetBytes("Invalid request");
socket.Send(bytes);
ServerLogs.ServerLog("Warning Sent");
Console.WriteLine("Warning Sent");
}
socket.BeginReceive(_buffer, 0, 1024, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
}
}
}//ServerLogs.cs >>>
class ServerLogs
{
private static string m_exePath = string.Empty;
public ServerLogs(string logMessage)
{
ServerLog(logMessage);
}
public static void ServerLog(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
try
{
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
{
Log(logMessage, w);
}
}
catch (Exception ex)
{
Console.WriteLine("Error: "+ex);
}
}
public static void Log(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\nLog Entry: ");
txtWriter.WriteLine("{0} {1} : {2}",
DateTime.Now.DayOfWeek, DateTime.Now.ToLongTimeString(), logMessage);
// txtWriter.WriteLine(" :");
// txtWriter.Write(" :{0}", logMessage);
// txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex);
}
}
}
First of all (for future use), you are way better of using the TcpClient and TcpListener classes instead, they make things much easier.
Secondly, I see no meaning in the flag boolean. It's completely useless. If you need to check something just do if(Textmessage.ToLower() == "x.exe") as it already returns a bool.
Thirdly and finally, your server stops receiving due to that you don't make it start waiting for data again after a command has been processed. After you've processed a valid command you call return; which will stop your code from calling the socket.BeginReceive() method.
else if(flag = Textmessage.ToLower() == "x.exe") //command from client
{
...code...
return; //<-- Your problem.
}
You should remove every return; that you have in your ReceiveCallback method, EXCEPT for the one in the block where you disconnect, since the others are useless. Once an if or else if block successfully executes the other ones will be ignored - meaning that you do not have to terminate the method.
Removing the returns will make your
socket.BeginReceive(_buffer, 0, 1024, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
line always execute, thus meaning that the server will keep reading commands until the connection is terminated.

Send objects over TCP with multiple clients and one server

Okay, I've been looking around and have found tutorials on both sending custom objects over TCP and also connecting multiple clients to one server, however I haven't been able to find an example of both so have decided to try it myself however I'm stuck. I so far have written a server that can handle an unlimited number of clients but have failed to implement sending of objects. This is the code I have so far for sending custom objects:
Client code:
Person p = new Person("Tyler", "Durden", 30); // create my serializable object
string serverIp = "127.0.0.1";
TcpClient client = new TcpClient(serverIp, 9050); // have my connection established with a Tcp Server
IFormatter formatter = new BinaryFormatter(); // the formatter that will serialize my object on my stream
NetworkStream strm = client.GetStream(); // the stream
formatter.Serialize(strm, p); // the serialization process
strm.Close();
client.Close();
Server code:
TcpListener server = new TcpListener(9050);
server.Start();
TcpClient client = server.AcceptTcpClient();
NetworkStream strm = client.GetStream();
IFormatter formatter = new BinaryFormatter();
Person p = (Person)formatter.Deserialize(strm); // you have to cast the deserialized object
strm.Close();
client.Close();
server.Stop();
This is the code I currently have for multiple clients:
Server code:
private ArrayList m_aryClients = new ArrayList(); //List of connected clients (Used for threading)
public Program()
{
//Empty constructor
}
static Program()
{
}
#region Main Enty Point
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
//Set log file location
setLogFileLocation("/usr/local/bin/ClipCloud/" + DateTime.Now.ToShortDateString() + ".log");
//Start the application
printAndLog("Starting server");
Program appmain = new Program();
//Get local hostname
IPAddress[] addressList = null;
string hostName = "";
try
{
hostName = Dns.GetHostName();
addressList = Dns.GetHostByName(hostName).AddressList;
}
catch (Exception ex)
{
printAndLog("Failed to get local address (" + ex.Message + ")", 1);
}
//Start listening and set up threads
if ((addressList == null ? false : (int)addressList.Length >= 1))
{
object[] objArray = new object[] { "Listening on : (", hostName, ") ", addressList[0], ",", 399 };
printAndLog(string.Concat(objArray), 0);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(addressList[0], 399));
socket.Listen(10);
socket.BeginAccept(new AsyncCallback(appmain.OnConnectRequest), socket);
//Wait until user types exit
while (!(Console.ReadLine().ToLower() == "exit"))
{}
printAndLog("Shutting down server");
socket.Close();
//Clean up after yourself
GC.Collect();
GC.WaitForPendingFinalizers();
printAndLog("Application successfully shutdown");
}
else
{
printAndLog("Unable to obtain local address" , 2);
}
}
#endregion
#region Server requests
public void NewConnection(Socket sockClient)
{
//new client connected
ClientHandler clientHandler = new ClientHandler(sockClient);
m_aryClients.Add(clientHandler);
printAndLog(string.Concat("Client (",clientHandler.Sock.RemoteEndPoint, ") connected"));
//Send client welcome message
DateTime now = DateTime.Now;
string str = string.Concat("{", now.ToString("G"), "}");
byte[] bytes = Encoding.ASCII.GetBytes(str.ToCharArray());
clientHandler.Sock.Send(bytes, (int)bytes.Length, SocketFlags.None);
clientHandler.SetupRecieveCallback(this);
}
public void OnConnectRequest(IAsyncResult ar)
{
try
{
Socket asyncState = (Socket)ar.AsyncState;
NewConnection(asyncState.EndAccept(ar));
asyncState.BeginAccept(new AsyncCallback(OnConnectRequest), asyncState);
}
catch (Exception ex)
{
printAndLog(ex.Message);
}
}
public void OnRecievedData(IAsyncResult ar)
{
ClientHandler asyncState = (ClientHandler)ar.AsyncState;
byte[] recievedData = asyncState.GetRecievedData(ar);
if ((int)recievedData.Length >= 1)
{
foreach (ClientHandler mAryClient in this.m_aryClients)
{
try
{
//This is where all data is sent out to all users!
mAryClient.Sock.Send(recievedData);
}
catch
{
printAndLog(string.Concat("Failed to send data to client (", asyncState.Sock.RemoteEndPoint, ")"), 2);
mAryClient.Sock.Close();
this.m_aryClients.Remove(asyncState);
return;
}
}
asyncState.SetupRecieveCallback(this);
}
else
{
printAndLog(string.Concat("Client (", asyncState.Sock.RemoteEndPoint, ") disconnected"), 0);
asyncState.Sock.Close();
this.m_aryClients.Remove(asyncState);
}
}
#endregion
}
internal class ClientHandler
{
private Socket m_sock;
private byte[] m_byBuff = new byte[50];
public Socket Sock
{
get
{
return this.m_sock;
}
}
public ClientHandler(Socket sock)
{
this.m_sock = sock;
}
public byte[] GetRecievedData(IAsyncResult ar)
{
int num = 0;
try
{
num = this.m_sock.EndReceive(ar);
}
catch
{
}
byte[] numArray = new byte[num];
Array.Copy(this.m_byBuff, numArray, num);
return numArray;
}
public void SetupRecieveCallback(Program app)
{
try
{
AsyncCallback asyncCallback = new AsyncCallback(app.OnRecievedData);
this.m_sock.BeginReceive(this.m_byBuff, 0, (int)this.m_byBuff.Length, SocketFlags.None, asyncCallback, this);
}
catch (Exception ex)
{
Console.WriteLine("Recieve callback setup failed! {0}", ex.Message);
}
}
}
Can someone please help me connecting the two.

Memory Leak in C# Socket application

I am trying to write an Server application which is listening on a particular port and waiting for devices to hit that port.Device connects every 30 seconds Once a device connects the device sends its MAC address. But the problem is the memory keeps on increasing and never frees up.
class Server
{
Object threadLock = new Object();
bool stopListening = false;
Socket clientSocket = null;
private void StartDeviceListener()
{
try
{
// create the socket
clientSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
// bind the listening socket to the port
IPEndPoint ep1 = new IPEndPoint(IPAddress.Any, 60000);
clientSocket.LingerState = new LingerOption(false, 0);
clientSocket.Bind(ep1);
clientSocket.Listen(10); //Waiting for Devices to connect.
do
{
// start listening
Console.WriteLine("Waiting for device connection on {0}....", 60000);
Socket deviceSocket = clientSocket.Accept();
//Console.WriteLine(deviceSocket.
#region ThreadPool
// ThreadPool.QueueUserWorkItem(ProcessRequest, (Object)deviceSocket);
Thread ts = new Thread(ProcessRequest);
ts.IsBackground = true;
ts.Start((Object)deviceSocket);
ts.Join();
#endregion
} while (!stopListening);
}
catch (Exception ex)
{
Console.WriteLine("exception... : " + ex.Message);
StartDeviceListener();
}
finally
{
if (clientSocket != null) { clientSocket.Close(); clientSocket = null; }
}
}
public void Stop()
{
try
{
stopListening = true;
if (clientSocket != null)
{
clientSocket.Disconnect(false);
clientSocket = null;
}
}
catch (Exception ex)
{
Console.WriteLine("exception : " + ex.Message);
}
}
void ProcessRequest(Object args)
{
using (Socket deviceSocket = args as Socket)
{
try
{
//lock the thread while we are creating the client IO Interface Manager
lock (threadLock)
{
byte[] readBuffer = new byte[1024];
// Read from buffer
int count = deviceSocket.Receive(readBuffer, 0, readBuffer.Length, SocketFlags.None);
String macAddress = "";//mac address sent by the device:
if (count > 0)
{
Encoding encoder = Encoding.ASCII;
int size = 0;
while (count > 0)
{
size += count;
// get string
macAddress += encoder.GetString(readBuffer, 0, count).Trim();
// Read from buffer
count = 0;
}
Console.WriteLine(string.Format("{0} trying to connect....", macAddress));
}
deviceSocket.Close();
readBuffer = null;
}
//threadLock = null;
}
catch (Exception ex)
{
Console.WriteLine("exception : " + ex.Message);
}
}
args = null;
}
public void Start()
{
StartDeviceListener();
}
}`
But the problem is the memory keeps on increasing and never frees up.
That is still a far cry from a memory-leak. You're probably chasing a problem that does not exist.
In the last shot you still have a working set of 10MB, that's practically zero.
When you really want to find/solve memory issues, use a profiler.

Categories