Hi there, to enhance my current Software i wanted to switch the datalogic to a server application that has faster connection to the database and is able to cache data.
So far i wrote a working server app and a client that connects to this server.
Currently i am experiencing a performance issue on the server side resulting in high cpu load and i wanted to ask if anyone might find the problem of it.
The server and client shall communicate async, so that multiple clients can work with the server and the server will later build up a queue if the operations reach higher levels.
Below you'll find the code, it's a bit messy since it's just a prototype by now.
I already read several articles on CP and the interwebs on that and i think that the problem might occur through the loop back to the start accept.
Why? -> Because since the accept is done async i expect 4 threads to get stuck on the endAccept, though this is just an assumption, but it seems it's at least one.
Also, if i stop the server (close listening and stuff) i always get an exception on the server part where the endAccept is.
Would be happy for any advice or hint to the problem.
Thanks in afvance
What I have tried:
I wrote the server like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Security.Cryptography.X509Certificates;
namespace ImsServer.ImsSockets
{
public class ServerSocket
{
private TcpListener _listeningSocket;
private readonly IPEndPoint _localEndPoint;
private ServerMain _serverMainUi;
List<TcpClient> _connectedClients = new List<TcpClient>(500);
private byte[] _bufferForMessages = new byte[256];
public ServerSocket(ServerMain InUi)
{
_localEndPoint = new IPEndPoint(IPAddress.Any, 12000);
_serverMainUi = InUi;
StartListening();
}
internal void StartListening()
{
try
{
_listeningSocket = new TcpListener(_localEndPoint);
_listeningSocket.Start(100);
StartAccept();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
internal void StartAccept()
{
AsyncCallback _asyncCallbackForAccept = ProcessAccept;
_listeningSocket.BeginAcceptTcpClient(_asyncCallbackForAccept, _listeningSocket);
}
private async void ProcessAccept(IAsyncResult InAcceptAsyncResult)
{
TcpListener _asyncListener = (TcpListener) InAcceptAsyncResult.AsyncState;
TcpClient _clientToAccept = _asyncListener.EndAcceptTcpClient(InAcceptAsyncResult);
await _serverMainUi.SetServerInformationText(Environment.NewLine + "Client : " + _clientToAccept.Client.LocalEndPoint + " Connected");
_connectedClients.Add(_clientToAccept);
NetworkStream _clientStream = _clientToAccept.GetStream();
_clientStream.ReadTimeout = 5000;
_clientStream.WriteTimeout = 5000;
int _clientIndex = _connectedClients.FindIndex(Cc => Cc == _clientToAccept);
byte[] _serverMessageToClient = Encoding.UTF8.GetBytes("You are connected to IMS-Server : Client No " + _clientIndex);
_clientStream.Write(_serverMessageToClient, 0, _serverMessageToClient.Length);
await _serverMainUi.SetServerInformationText(Environment.NewLine + "Connected Clients : " + _connectedClients.Count);
_clientStream.Flush();
StartAccept();
while(!_clientStream.DataAvailable) { }
_clientStream.BeginRead(_bufferForMessages, 0, _bufferForMessages.Length, ReceiveClientMessageCallback, _clientToAccept);
}
private async void ReceiveClientMessageCallback(IAsyncResult InAsyncResult)
{
TcpClient _client = (TcpClient)InAsyncResult.AsyncState;
if (_client.Connected)
{
NetworkStream _clientStream = _client.GetStream();
byte[] _clientMessage = _bufferForMessages;
int _noOfBytes = _clientStream.EndRead(InAsyncResult);
string _clientDecodedMessage = "";
_clientDecodedMessage = String.Concat(_clientDecodedMessage, Encoding.UTF8.GetString(_clientMessage, 0, _noOfBytes));
await _serverMainUi.SetServerInformationText(Environment.NewLine + "Client : " + _connectedClients.FindIndex(Cc => Cc == _client) + " wants to " + _clientDecodedMessage);
if (_clientDecodedMessage == "Disconnect")
{
byte[] _disconnectMessage = Encoding.UTF8.GetBytes("Bye");
_clientStream.Write(_disconnectMessage, 0, _disconnectMessage.Length);
_connectedClients.Remove(_client);
}
}
else
{
_client.Close();
}
}
private void AcceptRequestCompleted(object Sender, SocketAsyncEventArgs InArgs)
{
}
public bool ServerSocketStop()
{
bool _connectionsPending = _listeningSocket.Pending();
while(_connectionsPending) { }
_listeningSocket.Stop();
return true;
}
}
}
The client does this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ServerMiniTester
{
public partial class MainWindow : Window
{
private TcpClient _client;
private byte[] _serverResponse = new byte[256];
public MainWindow()
{
InitializeComponent();
}
private void BtConnectToServerClick(object sender, RoutedEventArgs e)
{
_client = new TcpClient();
try
{
_client.Connect(IPAddress.Parse("10.176.2.8"),12000);
while(!_client.Connected) { }
NetworkStream _clientStream = _client.GetStream();
AsyncCallback _receiveServerMessage = ReceiveServerMessageCallback;
_serverResponse = new byte[256];
_clientStream.BeginRead(_serverResponse, 0, _serverResponse.Length, _receiveServerMessage, _client);
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
}
}
private void BtDisconnectServerClick(object Sender, RoutedEventArgs E)
{
try
{
NetworkStream _clientStream = _client.GetStream();
byte[] _disconnectMessage = Encoding.UTF8.GetBytes("Disconnect");
_clientStream.Write(_disconnectMessage, 0, _disconnectMessage.Length);
while(!_clientStream.DataAvailable) { Thread.Sleep(50);}
AsyncCallback _receiveServerMessage = ReceiveServerMessageCallback;
_serverResponse = new byte[256];
_clientStream.BeginRead(_serverResponse, 0, _serverResponse.Length, _receiveServerMessage, _client);
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
}
}
private async void ReceiveServerMessageCallback(IAsyncResult InAsyncResult)
{
NetworkStream _clientStream = ((TcpClient)InAsyncResult.AsyncState).GetStream();
byte[] _serverMessage = _serverResponse;
int _noOfBytes = _clientStream.EndRead(InAsyncResult);
string _serverDecodedMessage = "";
_serverDecodedMessage = String.Concat(_serverDecodedMessage, Encoding.UTF8.GetString(_serverMessage, 0, _noOfBytes));
if (_serverDecodedMessage == "Bye")
{
await SetClientInformationText(Environment.NewLine + "Server response : " + _serverDecodedMessage +
Environment.NewLine + "*****Server accepted Disconnect*****");
_client.Close();
_client.Dispose();
await SetClientInformationText(Environment.NewLine + "*****Disconnected from Server*****");
}
else
{
await SetClientInformationText(Environment.NewLine + "Server response : " + _serverDecodedMessage);
}
}
public async Task SetClientInformationText(string InText)
{
await LbServerResponse.Dispatcher.InvokeAsync(() => LbServerResponse.Text += InText);
}
private bool ValidateServerCertificate(Object Sender, X509Certificate InCertificate, X509Chain InChain, SslPolicyErrors InSslPolicyErrors)
{
return true;
}
}
}