Help: DotNet Tcp Client Bound

 Hi All,

I am using a TCP server to accept connections from n TCP clients (with Socket.Select()).  It seems that there is a strange bound on the value of n in Socket.Select. Sad

Steps to reproduce the problem.

1. Bring up a TCP server on port 19999 in a thread.  This thread use a socket arraylist as the first parameter for Socket.Select().
2. Bring up client threads one at a time, with 1 second inteval between two client threads.  Each thread creates a client and connects to that server.  The number of client thread is n.
3.  When 
the number of n reaches 65, I got an exception at Socket.Select().  The message is  "Index was outside the bounds of the array".

I tried SetSocketOption with MaxConnections and get an unhandled exception.  I also 
tried to use different value for socket Listen(int), for example, 100, 255, and 10000.  It does not help. Then I played around with the keepalive option.  Nothing changes.

Please help me if you have any suggestions!  Thanks in advanced!

ps. The test code of client thread, server thread, and main is attached.  It is for vs2003 DotNet 1.0.  I also tested it with vs2005 DotNet 2.0, the problem is the same.

 Tao


using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

 public class MyTest
{

       public MyTest () {
      }


    static void Main(string [] args)
        {
 
            Thread s = new Thread(new ThreadStart(MyTest.Server1));
            s.Name="Server";
            s.Start();

            Thread c1 = null;
         
            for (int i=0; i<100; i++)
            {
                c1 = new Thread(new ThreadStart(MyTest.Client1));
                c1.Name=i.ToString();
                c1.Start();
                Thread.Sleep(1000);
            }

            Console.WriteLine("All threads are up.");
            Thread.Sleep(10000);
            Environment.Exit(-1);
    }


        public static void Server1()
        {
            Socket lisenterSocket = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);
            lisenterSocket.Bind(new IPEndPoint(IPAddress.Loopback, 19999));
            lisenterSocket.Listen(10000);

            Console.WriteLine("Server1: "+DateTime.Now.ToString("HH-mm-ss.fff")
                +" Tcp server up at "
                +IPv4Address.Loopback.ToString());

            ArrayList allSocketList = new ArrayList();
            ArrayList socketList = new ArrayList();
 
            allSocketList.Add(lisenterSocket);
            socketList.Add(lisenterSocket);

            while (true)
            {
                Thread.Sleep(100);
                Console.WriteLine("");
                Console.WriteLine("Server1: "+DateTime.Now.ToString("HH-mm-ss.fff")
                    +" select "+socketList.Count+" sockets");

                try
                {
                    Socket.Select(socketList, null, null, 500000000);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    Environment.Exit(-2);
                }

                Console.WriteLine("Server1: "+DateTime.Now.ToString("HH-mm-ss.fff")
                    +" "+socketList.Count
                    +" sockets got connection requests.");

             
                for (int j=0; j<socketList.Count; j++)
                {
                    Console.WriteLine("Server1: "+DateTime.Now.ToString("HH-mm-ss.fff")
                        +" get socketList["+(j+1)+" out of "+socketList.Count+"]");
                    Socket activeSocket = ((Socket)socketList[j]);
                    if (activeSocket==lisenterSocket)
                    {
                      //New client connection
                        Socket acceptedSocket = lisenterSocket.Accept();

                        //Back up this socket                   
                        allSocketList.Add(acceptedSocket);

                        Console.WriteLine("Server1: "+DateTime.Now.ToString("HH-mm-ss.fff")
                            +" allSocketList size = "+allSocketList.Count);
                    }
                    else
                    { 
                        byte [] buff = new byte [2000];
                        int size = activeSocket.Receive(buff);

                        MemoryStream ms = new MemoryStream(buff);
                        BinaryReader br = new BinaryReader(ms);
                        int clientIndex = br.ReadInt32();

                        Console.WriteLine("Server1: "+DateTime.Now.ToString("HH-mm-ss.fff")
                            +" received client "+clientIndex+"'s message.");
                     
                    }
                }

                Console.WriteLine("Server1: "+DateTime.Now.ToString("HH-mm-ss.fff")
                    +" reset socketList to size of "+(allSocketList.Count));

                socketList.Clear();
                for (int k=0; k<allSocketList.Count; k++)
                {
                    socketList.Add(allSocketList[k]);
                }

                //If we get 100 clients, quit.
                if (allSocketList.Count == 100)
                {
                    Console.WriteLine("");
                    Console.WriteLine("Got 100 clients.  Quit.");
                    Console.WriteLine("");
                    Environment.Exit(-1);
                }
             
            }

        }

        public static void Client1()
        {
            int name = int.Parse(Thread.CurrentThread.Name);

            Console.WriteLine("Client1: "+name+" "+
                DateTime.Now.ToString("HH-mm-ss.fff")+" connect");

            Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Loopback, 19999);
         
         
            try
            {
            c.Connect(remoteEndPoint);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Environment.Exit(-1);
            }

            Console.WriteLine("Client1: "+name+" "+
                DateTime.Now.ToString("HH-mm-ss.fff")+" connected");         


            byte [] buf = new byte [4];
            MemoryStream ms = new MemoryStream(buf);
            BinaryWriter bw = new BinaryWriter(ms);
            bw.Write(name);

            while (true)
            {
                int result = c.Send(buf);
                Console.WriteLine("Client1: "+name+
                    " "+DateTime.Now.ToString("HH-mm-ss.fff")
                    +" sent "+result+" bytes out");

                //Just blocks this client socket until the program quits
                 lock(bw)
                {
                    Monitor.Wait(bw);
                }
            }

        }



}

 



Answer this question

Help: DotNet Tcp Client Bound

  • Alexander75

    The link you provided is really helpful.  Really appreciate your answers!

     

  • Mani Swaminathan

    Hi Durgaprasad Gorti,

    Thank you very much for your reply!

    It seems that I have to implement a select-like class to support larger number of clients.   

    I searched MSDN for .net framework.  There is no keyword WSAEventSelect or WSAAsyncSelect.  There is an example when I search WaitForMultipleObjects:
    <SDK>v1.1\Samples\Technologies\Threading\WaitSynchronization. 

    As of now, I am not sure that is what I want.  I have no experience in Async  programming.  So could you please point out some other starting references such as a C# class or some key words   Thank you very much!

     Tao

  • NeoDiO12639

    Select eventually calls one of the variants of
    WSAEventSelect or WSAAsyncSelect which eventually calls
    WaitForMultipleObjects which has a limit of 
    MAXIMUM_WAIT_OBJECTS which is defined as
    #define MAXIMUM_WAIT_OBJECTS 64

    So YES this is a limitation of Select method.
    You should rather be using Async programming style which scales up much better than the select methods. Select method is old style and
    is not really the scalable way to program many clients


  • SecurityAdmin

    Quit the Select.
    Do the async programming. You will realize that it is simpler and
    does the job much more effectively.
    Async is a just a tad difficult to undefrstand but there are TONS of resources to help you get started. I strongly recommend that you take time to read and educate yourself and then go back and solve the problem you are trying to solve.

    Try the following
    http://msdn.microsoft.com/library/default.asp url=/library/en-us/cpguide/html/cpovrasynchronousprogrammingoverview.asp
    http://blogs.msdn.com/cbrumme/search.aspx q=async&p=1

    and follow some quick starts on the web

  • Help: DotNet Tcp Client Bound