How create multiclient(multithread) SSL Socket Server C# ?

Created at 12 Apr 2015, 12:53
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
mindbreaker's avatar

mindbreaker

Joined 19.07.2014

How create multiclient(multithread) SSL Socket Server C# ?
12 Apr 2015, 12:53


Hello All,

How create SSL multiuser or multithread server (multiple connection) from this code:

or maybe someone know good example but only SSL version ?

using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.IO;

namespace SSLServer
{
    public sealed class SslTcpServer
    {
        static X509Certificate serverCertificate = null;

        public static void RunServer(string certificate)
        {

            // StartSSL.com certs pfx(p12) file with cert: CN=ssl.domain.com
            serverCertificate = new X509Certificate2("ssl.p12", "KeyPassword");

            // Create a TCP/IP (IPv4) socket and listen for incoming connections.
            TcpListener listener = new TcpListener(IPAddress.Any, 8080);
            listener.Start();
            while (true)
            {
                Console.WriteLine("Waiting for a client to connect...");
                // Application blocks while waiting for an incoming connection.
                // Type CNTL-C to terminate the server.
                TcpClient client = listener.AcceptTcpClient();
                ProcessClient(client);
            }
        }


        static void ProcessClient(TcpClient client)
        {
            SslStream sslStream = new SslStream(client.GetStream(), false);
            try
            {
                sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);

                 sslStream.ReadTimeout = 5000;
                sslStream.WriteTimeout = 5000;
                // Read a message from the client.  
                Console.WriteLine("Waiting for client message...");
                string messageData = ReadMessage(sslStream);
                Console.WriteLine("Received: {0}", messageData);

                // Write a message to the client.
                byte[] message = Encoding.UTF8.GetBytes("Hello from the server.");
                Console.WriteLine("Sending hello message.");
                sslStream.Write(message);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                }
                Console.WriteLine("Authentication failed - closing the connection.");
                sslStream.Close();
                client.Close();
                return;
            }
            finally
            {
                sslStream.Close();
                client.Close();
            }
        }
        static string ReadMessage(SslStream sslStream)
        {
            // Read the  message sent by the client.
            // The client signals the end of the message using the
            // "" marker.
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                // Read the client's test message.
                bytes = sslStream.Read(buffer, 0, buffer.Length);

                // Use Decoder class to convert from bytes to UTF8
                // in case a character spans two buffers.
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);
                // Check for EOF or an empty message.
                if (messageData.ToString().IndexOf("") != -1)
                {
                    break;
                }
            } while (bytes != 0);

            return messageData.ToString();
        }

        public static void Main(string[] args)
        {

            string certificate = "";
            try
            {
                SslTcpServer.RunServer(certificate);
            }
            catch (Exception e)
            {
                Console.WriteLine("error");
                Console.ReadLine();
            }
            //return 0;
        }
    }
}

Thanks ...

Bye.


@mindbreaker
Replies

ClickAlgo
13 Apr 2015, 09:52

Hi,

If you are using the .NET framework version 4.5 look into the Task Parallel Library

The Task Parallel Library (TPL) is based on the concept of a task, which represents an asynchronous operation. In some ways, a task resembles a thread or ThreadPool work item, but at a higher level of abstraction. The term task parallelism refers to one or more independent tasks running concurrently

https://msdn.microsoft.com/en-us/library/dd537609%28v=vs.110%29.aspx

Just refactor your code to implement this architecture.

 


@ClickAlgo

mindbreaker
13 Apr 2015, 14:33

RE:

Paul_Hayes said:

Hi,

If you are using the .NET framework version 4.5 look into the Task Parallel Library

The Task Parallel Library (TPL) is based on the concept of a task, which represents an asynchronous operation. In some ways, a task resembles a thread or ThreadPool work item, but at a higher level of abstraction. The term task parallelism refers to one or more independent tasks running concurrently

https://msdn.microsoft.com/en-us/library/dd537609%28v=vs.110%29.aspx

Just refactor your code to implement this architecture.

 

Thank you very much.


@mindbreaker

mindbreaker
15 Apr 2015, 17:11

sslstream end

Hi all,

Multi ssl server and client from calgo

It does not work correctly client dont Print server message why?

Client:

// System
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
// cAlgo
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.API.Requests;
using cAlgo.Indicators;
using System.Collections;
using System.Collections.Generic;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;


namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class OnePositionClient : Robot
    {

        [Parameter("Username", DefaultValue = "")]
        public string Username { get; set; }

        [Parameter("Password", DefaultValue = "")]
        public string Password { get; set; }

        [Parameter("MoneyForSignalUSD", DefaultValue = 100, MinValue = 100)]
        public int MoneyForSignalUSD { get; set; }

        List<string> PosOpenID = new List<string>();
        List<string> PosCloseID = new List<string>();
        List<string> PosServerID = new List<string>();
        List<string> PosServerAll = new List<string>();

        public static string txt = "";

        private static Hashtable certificateErrors = new Hashtable();

        protected override void OnTick()
        {
            ConnectSSL("HelloServer" + Symbol);
        }


//================================================================================================================
//                                                                                   End Send POST to HTTPS Server
//================================================================================================================

        // The following method is invoked by the RemoteCertificateValidationDelegate.
        public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
                return true;

            Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

            // Do not allow this client to communicate with unauthenticated servers.
            //return false;
            //Force ssl certyfikates as correct
            return true;
        }


        public void ConnectSSL(string msg = "")
        {

            txt = "";
            try
            {
                TcpClient client = new TcpClient("localhost", 8080);

                // Create an SSL stream that will close the client's stream.
                SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
                try
                {
                    sslStream.AuthenticateAsClient("ssl.breakermind.com");
                } catch (AuthenticationException e)
                {
                    Console.WriteLine("Exception: {0}", e.Message);
                    if (e.InnerException != null)
                    {
                        Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                    }
                    Console.WriteLine("Authentication failed - closing the connection.");
                    client.Close();
                    return;
                }
                int j = 10;
                byte[] messsage = Encoding.UTF8.GetBytes(msg + (char)j);
                // Send hello message to the server.
                Print("Send msg " + msg);
                sslStream.Write(messsage);
                sslStream.Flush();

                // Read message from the server.
                int i = -1;
                while ((i = sslStream.ReadByte()) != 10)
                {
                    txt = txt + (char)i;
                    if (i == -1)
                    {
                        Console.WriteLine("Server says: {0}", txt);
                        break;
                    }
                }
                Console.WriteLine("Server says: {0}", txt);
                // Close the client connection.

                client.Close();
                Console.WriteLine("Client closed.");

            } catch (ArgumentNullException e)
            {
                Print("ArgumentNullException: {0}", e);
            } catch (SocketException e)
            {
                Print("SocketException: {0}", e);
            }

        }


        public void Connect(string PosAll = "")
        {
            ///===========================================================

            string pos = "SET#" + "1#";
            //pos = pos + "SPREAD:" + Symbol.Spread + "|";
            pos = pos + PosAll;
            // end of stream
            pos = pos + '\0';

            // Process the data sent by the client.
            Print("String " + pos);
            ////===========================================================



            try
            {
                TcpClient client = new TcpClient("localhost", 8080);
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(pos);
                NetworkStream stream = client.GetStream();
                stream.Write(data, 0, data.Length);
                Print("Sent: " + pos);
                data = new Byte[1024];
                Int32 bytes = stream.Read(data, 0, data.Length);
                string responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                Print("Received: {0}", responseData);
                // Close everything.
                stream.Close();
                client.Close();

            } catch (ArgumentNullException e)
            {
                Print("ArgumentNullException: {0}", e);
            } catch (SocketException e)
            {
                Print("SocketException: {0}", e);
            }

        }


    }
}


//====================================================================================================================
//                                                                                                Initialize Positions
//====================================================================================================================

Server multi ssl

using System;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Security.Authentication;

namespace server
{
    public class server
    {

        private string positions = "";
        // Declare a two dimensional array 
        // users allowed 10
        private static int maxSlots = 11;
        private string[,] posArray = new string[maxSlots + 1, 1];
        X509Certificate serverCertificate = new X509Certificate2("ssl.p12", "KeyPass");

        ManualResetEvent tcpClientConnected = new ManualResetEvent(false);

        static void DisplayCertificateInformation(SslStream stream)
        {
            Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus);

            X509Certificate localCertificate = stream.LocalCertificate;
            if (stream.LocalCertificate != null)
            {
                Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.",
                    localCertificate.Subject,
                    localCertificate.GetEffectiveDateString(),
                    localCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("Local certificate is null.");
            }
            // Display the properties of the client's certificate.
            X509Certificate remoteCertificate = stream.RemoteCertificate;
            if (stream.RemoteCertificate != null)
            {
                Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.",
                    remoteCertificate.Subject,
                    remoteCertificate.GetEffectiveDateString(),
                    remoteCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("Remote certificate is null.");
            }
        }

        static string ReadMessage(SslStream sslStream)
        {
            // Read the  message sent by the client.
            // The client signals the end of the message using the
            // "" marker.
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                // Read the client's test message.
                bytes = sslStream.ReadByte();

                // Use Decoder class to convert from bytes to UTF8
                // in case a character spans two buffers.
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char znak = (char)bytes;
                messageData.Append(znak);
                // Check for EOF or an empty message.
                if (messageData.ToString().IndexOf("") != -1)
                {
                    break;
                }
            } while (bytes != 0);

            return messageData.ToString();
        }

        void ProcessIncomingData(object obj)
        {
            SslStream sslStream = (SslStream)obj;
            //string ip = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString();

            //Console.WriteLine("Client IP : " + ip);


            string sb = "";
            int i = -1;
            try
            {
                while (true)
                {
                    int j = 10;
                    //Console.WriteLine((char)j);
                    while ((i = sslStream.ReadByte()) != 10)
                    {
                        sb = sb + (char)i;
                       // Console.WriteLine("Stream in char " +  i);
                        if (i == -1) break;
                    }
                    Console.WriteLine("Client " + sb);
                    byte[] messsage = Encoding.UTF8.GetBytes("Helloclient" + (char)j);
                    // Send hello message to the server.
                    sslStream.Write(messsage);
                    sslStream.Flush();

                }

            }
            catch (Exception e) { }

        }

        void ProcessIncomingConnection(IAsyncResult ar)
        {
            TcpListener listener = (TcpListener)ar.AsyncState;
            TcpClient client = listener.EndAcceptTcpClient(ar);
            SslStream sslStream = new SslStream(client.GetStream(), false);
            try
            {
                
                sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);
                //DisplayCertificateInformation(sslStream);
            }catch(Exception e){
                Console.WriteLine("Client no ssl" + client);
            client.Close();
            }

            
            
            ThreadPool.QueueUserWorkItem(ProcessIncomingData, sslStream);
            tcpClientConnected.Set();
        }

        public void start()
        {
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080);
            TcpListener listener = new TcpListener(endpoint);
            listener.Start();

            while (true)
            {
                tcpClientConnected.Reset();
                listener.BeginAcceptTcpClient(new AsyncCallback(ProcessIncomingConnection), listener);
                tcpClientConnected.WaitOne();
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("Multi user server. Recive save and send data to clients max 10 accounts.");
            //DateTime.Now.ToLongTimeString()
            Console.WriteLine(DateTime.Now + " Waiting for connections....");
            try
            {
                server s = new server();
                s.start();
            }
            catch (Exception e) { }
        }
    }
}

Thanks.


@mindbreaker

mindbreaker
15 Apr 2015, 18:22

Working

Works (SSL cAlgo Client send Symbol Bid Ask to the Server C#):

 

Server SSL C# MultiConnection

Server.cs

using System;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Security.Authentication;

namespace server
{
    public class server
    {

        private string positions = "";
        // Declare a two dimensional array 
        // users allowed 10
        private static int maxSlots = 11;
        private string[,] posArray = new string[maxSlots + 1, 1];
        X509Certificate serverCertificate = new X509Certificate2("ssl.p12", "KeyPass");

        ManualResetEvent tcpClientConnected = new ManualResetEvent(false);

        static void DisplayCertificateInformation(SslStream stream)
        {
            Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus);

            X509Certificate localCertificate = stream.LocalCertificate;
            if (stream.LocalCertificate != null)
            {
                Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.",
                    localCertificate.Subject,
                    localCertificate.GetEffectiveDateString(),
                    localCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("Local certificate is null.");
            }
            // Display the properties of the client's certificate.
            X509Certificate remoteCertificate = stream.RemoteCertificate;
            if (stream.RemoteCertificate != null)
            {
                Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.",
                    remoteCertificate.Subject,
                    remoteCertificate.GetEffectiveDateString(),
                    remoteCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("Remote certificate is null.");
            }
        }

                static string ReadMessage(SslStream sslStream)
        {
            // Read the  message sent by the client. 
            // The client signals the end of the message using the 
            // "<EOF>" marker.
            byte [] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                // Read the client's test message.
                bytes = sslStream.Read(buffer, 0, buffer.Length);

                // Use Decoder class to convert from bytes to UTF8 
                // in case a character spans two buffers.
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer,0,bytes)];
                decoder.GetChars(buffer, 0, bytes, chars,0);
                messageData.Append (chars);
                // Check for EOF or an empty message. 
                if (messageData.ToString().IndexOf("<EOF>") != -1)
                {
                    break;
                }
            } while (bytes !=0); 

            return messageData.ToString();
        }


        void ProcessIncomingData(object obj)
        {
            SslStream sslStream = (SslStream)obj;
            try{
                // Set timeouts for the read and write to 5 seconds.
                sslStream.ReadTimeout = 5000;
                sslStream.WriteTimeout = 5000;
                // Read a message from the client.   
                Console.WriteLine("Waiting for client message...");
                string messageData = ReadMessage(sslStream);
                Console.WriteLine("Received: {0}", messageData);

                // Write a message to the client. 
                byte[] message = Encoding.UTF8.GetBytes("Hello from the server.<EOF>");
                Console.WriteLine("Sending hello message.");
                sslStream.Write(message);
                sslStream.Flush();

            }
            catch (Exception e) { }

        }

        void ProcessIncomingConnection(IAsyncResult ar)
        {
            TcpListener listener = (TcpListener)ar.AsyncState;
            TcpClient client = listener.EndAcceptTcpClient(ar);
            SslStream sslStream = new SslStream(client.GetStream(), false);
            try
            {

                sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);
                //DisplayCertificateInformation(sslStream);
            }
            catch (Exception e)
            {
                Console.WriteLine("Client no ssl" + client);
                client.Close();
            }



            ThreadPool.QueueUserWorkItem(ProcessIncomingData, sslStream);
            tcpClientConnected.Set();
        }

        public void start()
        {
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080);
            TcpListener listener = new TcpListener(endpoint);
            listener.Start();

            while (true)
            {
                tcpClientConnected.Reset();
                listener.BeginAcceptTcpClient(new AsyncCallback(ProcessIncomingConnection), listener);
                tcpClientConnected.WaitOne();
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("Multi user server. Recive save and send data to clients max 10 accounts.");
            //DateTime.Now.ToLongTimeString()
            Console.WriteLine(DateTime.Now + " Waiting for connections....");
            try
            {
                server s = new server();
                s.start();
            }
            catch (Exception e) { }
        }
    }
}

 

Client.algo

// System
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
// cAlgo
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.API.Requests;
using cAlgo.Indicators;
using System.Collections;
using System.Collections.Generic;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class OnePositionClient : Robot
    {

        // "Server SSL Certyficate (CN=www.domain.com)"
        public string hostname = "www.example.com";

        // "Server host www.example.com"
        public string host = "www.example.com";

        // "Server port"
        public int port = 8080;

        List<string> PosOpenID = new List<string>();

        public static string txt = "";

        private static Hashtable certificateErrors = new Hashtable();

        protected override void OnBar()
        {
            ConnectSSL("Hello Server " + Symbol);
        }


//================================================================================================================
//                                                                                  SSL Socket client Data send
//================================================================================================================

        // The following method is invoked by the RemoteCertificateValidationDelegate.
        public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
                return true;

            Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

            // Do not allow this client to communicate with unauthenticated servers when false.
            //return false;
            //Force ssl certyfikates as correct
            return true;
        }

        static string ReadMessage(SslStream sslStream)
        {
            // Read the  message sent by the server. 
            // The end of the message is signaled using the 
            // "<EOF>" marker.
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                bytes = sslStream.Read(buffer, 0, buffer.Length);

                // Use Decoder class to convert from bytes to UTF8 
                // in case a character spans two buffers.
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);
                // Check for EOF. 
                if (messageData.ToString().IndexOf("<EOF>") != -1)
                {
                    break;
                }
            } while (bytes != 0);

            return messageData.ToString();
        }


        public void ConnectSSL(string msg = "")
        {

            txt = "";
            try
            {
                TcpClient client = new TcpClient(host, port);

                // Create an SSL stream that will close the client's stream.
                SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
                try
                {
                    sslStream.AuthenticateAsClient(hostname);
                } catch (AuthenticationException e)
                {
                    Console.WriteLine("Exception: {0}", e.Message);
                    if (e.InnerException != null)
                    {
                        Print("Inner exception: {0}", e.InnerException.Message);
                    }
                    Print("Authentication failed - closing the connection.");
                    client.Close();
                    return;
                }


                // Signal the end of the message using the "<EOF>".
                // Semd message
                byte[] messsage = Encoding.UTF8.GetBytes(msg + " <EOF>");
                // Send hello message to the server. 
                sslStream.Write(messsage);
                sslStream.Flush();
                // Read message from the server. 
                string serverMessage = ReadMessage(sslStream);
                Print("Server says: {0}", serverMessage);
                // Close the client connection.
                client.Close();
                Print("Client closed.");


            } catch (ArgumentNullException e)
            {
                Print("ArgumentNullException: {0}", e);
            } catch (SocketException e)
            {
                Print("SocketException: {0}", e);
            }

        }


    }
}

 


@mindbreaker

mindbreaker
15 Apr 2015, 18:24

RE: Working

This post was removed by moderator.


@mindbreaker