hikalkan / scs

TCP Server/Client Communication and RMI Framework
MIT License
225 stars 112 forks source link

Problem with stress testing #11

Open Zhong-Tong opened 8 years ago

Zhong-Tong commented 8 years ago

Hi,

First of all, thanks for your great work on the project! I'm having an issue with stress testing, when the clients communicate with the server in a parallel way, I would got a AccessViolationException from mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback.

I'm suspecting it's caused by TcpClient EndReceive method but cannot approve it. The code sample can be found here:

Client App:

class Program
{
    static List<string> clients = new List<string>() { };

    static void Main()
    {
        for (int i = 0; i < 1000; i++)
        {
            clients.Add(i.ToString());
        }

        Thread worker = new Thread(ThreadTask);
        worker.IsBackground = true;
        worker.Start();

        Console.WriteLine("Press enter to disconnect from server...");
        Console.ReadLine(); //Wait user to press enter

    }

    static void ThreadTask()
    {
        Parallel.ForEach(clients, c =>
        {
            new Action(() =>
            {
                CreateClient(c);
            }).Invoke();
        });
    }

    static void CreateClient(string c)
    {
        while (true)
        {
            Console.Write(c + ", ");
            for (int i = 0; i < 5; i++)
            {
                //Create a client object to connect a server on 127.0.0.1 (local) IP and listens 10085 TCP port
                using (var client = ScsClientFactory.CreateClient(new ScsTcpEndPoint("127.0.0.1", 10085)))
                {
                    try
                    {
                        //Create a SynchronizedMessenger that uses the client as internal messenger.
                        using (var synchronizedMessenger = new SynchronizedMessenger<IScsClient>(client))
                        {
                            client.Connect(); //Connect to the server
                            synchronizedMessenger.Start(); //Start synchronized messenger messenger

                            var messageText = "MESSAGE FROM CLIENT:" + c; //Get a message from user

                            //Send a message to the server
                            synchronizedMessenger.SendMessage(new ScsTextMessage(messageText));

                            //Receive a message from the server
                            var receivedMessage = synchronizedMessenger.ReceiveMessage<ScsTextMessage>();

                            Thread.Sleep(200);

                            synchronizedMessenger.Stop(); //Stop synchronized messenger messenger

                            Thread.Sleep(200);

                            client.Disconnect(); //Disconnect to the server
                        }
                    }
                    catch { }
                }

                Thread.Sleep(1000);

            }

            Thread.Sleep(5000);
        }
    }

}

Server App:

class Program
{
    static void Main()
    {
        //Create a server that listens 10085 TCP port for incoming connections
        var server = ScsServerFactory.CreateServer(new ScsTcpEndPoint(10085));

        //Register events of the server to be informed about clients
        server.ClientConnected += Server_ClientConnected;
        server.ClientDisconnected += Server_ClientDisconnected;

        server.Start(); //Start the server

        Console.WriteLine("Server is started successfully. Press enter to stop...");
        Console.ReadLine(); //Wait user to press enter

        server.Stop(); //Stop the server
    }

    static void Server_ClientConnected(object sender, ServerClientEventArgs e)
    {
        Console.WriteLine("A new client is connected. Client Id = " + e.Client.ClientId);

        //Register to MessageReceived event to receive messages from new client
        e.Client.MessageReceived += Client_MessageReceived;
    }

    static void Server_ClientDisconnected(object sender, ServerClientEventArgs e)
    {
        Console.WriteLine("A client is disconnected! Client Id = " + e.Client.ClientId);
    }

    static void Client_MessageReceived(object sender, MessageEventArgs e)
    {
        var message = e.Message as ScsTextMessage; //Server only accepts text messages
        if (message == null)
        {
            return;
        }

        //Get a reference to the client
        var client = (IScsServerClient)sender;

        Console.WriteLine(message.Text + " FROM CLIENT - " + client.ClientId);

        //Send reply message to the client
        client.SendMessage(
            new ScsTextMessage(
                "ACK",
                message.MessageId //Set first message's id as replied message id
                ));
    }
}

Please kindly have a test and suggest.

Regards,

Tong