Ошибка в методе Socket.Select(...)
От: Nickolay Ch  
Дата: 19.06.04 15:47
Оценка:
При написании проекта типа клинет-сервер возникла проблема:
Сервер для обслуживания клиентов применяет метод Socket.Select(IList checkRead, IList checkWrite, IList checkError, int microSeconds);
При подсоединении 64го клинента происходит обвал программы по IndexOutOfRangeException.
Ниэе приведу код модели сервера(просто слушат сокет, acceptит входящие коннекты и добавляет клиентские сокеты в ArrayList checkList для прослушки):
В качестве клиента использовался telnet.
64ый коннект — и валится. Обвал происходит в приватном методе Socketа: SocketListTofileDescriptorSet(...)
На microsoft.com глухо — ни слова об этом.
Декомпильнул mscorelib, и там прям в коде прошита константа: 64 — размер входного множества для Select.
Так что большее число клиентов обслужить с помощью Selecta неудасться.
Даже причина этому быда найдена в хелпе по Microsoft Winsock 2 для Delphi :

Four macros are defined in the header file WINSOCK2.H for manipulating and checking the descriptor sets. The variable FD_SETSIZE determines the maximum number of descriptors in a set. (The default value of FD_SETSIZE is 64, which can be modified by #defining FD_SETSIZE to another value before #including WINSOCK2.H.)

Так вот — при программировании под ВинАпи можно опеределить сколько проге надо сокетов послушать. Под .Нет выходит, что нельзя.
Вопрос — поделитесь кто-нить, пожалуйста опытом — как писать сервер, рассчитанный на большое число клиентов(~ неск. тысяч).
Модель — на каждого клиента заводится отдельный поток/процесс — не годится.

Код модели сервера:

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections;

namespace TestSock
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class Class1
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {            
                        IPHostEntry ipHostEntry = Dns.Resolve("localhost");
            IPAddress ipAddress = ipHostEntry.AddressList[0];

    
            ArrayList listenList = new ArrayList();
            ArrayList acceptList = new ArrayList();

            Socket sock = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream,
                ProtocolType.Tcp);
            sock.Bind(new IPEndPoint(ipAddress, 11000));
            sock.Listen(10);
            
            string msg = "hello";
            byte [] bytes = Encoding.ASCII.GetBytes(msg);
            while (true)
            {
                try
                {
                    listenList.Add(sock);
                    Socket.Select(listenList, null, null, 1000);
                    try
                    {
                    
                        foreach (Socket s in listenList )
                        {
                            Socket conn = s.Accept();
                            acceptList.Add(conn);
                            conn.Send(bytes);
                            Console.WriteLine("Connected clients: {0}", acceptList.Count);                
                        }
                        listenList.Clear();
                        foreach(Socket s in acceptList )
                        {
                            listenList.Add(s);
                        }
                    }
                    catch(SocketException ex)
                    {
                    
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception occured: {0}\nStackTrace:{1}\nPress any key to continue", ex.Message, ex.StackTrace);
                    Console.ReadLine();
                    break;
                }
            }
        }
}
Re: Ошибка в методе Socket.Select(...)
От: Echer  
Дата: 22.06.05 06:51
Оценка:
Здравствуйте, Nickolay Ch, Вы писали:

NC>При написании проекта типа клинет-сервер возникла проблема:

NC>Сервер для обслуживания клиентов применяет метод Socket.Select(IList checkRead, IList checkWrite, IList checkError, int microSeconds);
NC>При подсоединении 64го клинента происходит обвал программы по IndexOutOfRangeException.
NC>Ниэе приведу код модели сервера(просто слушат сокет, acceptит входящие коннекты и добавляет клиентские сокеты в ArrayList checkList для прослушки):
NC>В качестве клиента использовался telnet.
NC>64ый коннект — и валится. Обвал происходит в приватном методе Socketа: SocketListTofileDescriptorSet(...)
NC>На microsoft.com глухо — ни слова об этом.
NC>Декомпильнул mscorelib, и там прям в коде прошита константа: 64 — размер входного множества для Select.
NC>Так что большее число клиентов обслужить с помощью Selecta неудасться.
NC>Даже причина этому быда найдена в хелпе по Microsoft Winsock 2 для Delphi :
NC>

NC>Four macros are defined in the header file WINSOCK2.H for manipulating and checking the descriptor sets. The variable FD_SETSIZE determines the maximum number of descriptors in a set. (The default value of FD_SETSIZE is 64, which can be modified by #defining FD_SETSIZE to another value before #including WINSOCK2.H.)

NC>Так вот — при программировании под ВинАпи можно опеределить сколько проге надо сокетов послушать. Под .Нет выходит, что нельзя.
NC>Вопрос — поделитесь кто-нить, пожалуйста опытом — как писать сервер, рассчитанный на большое число клиентов(~ неск. тысяч).
NC>Модель — на каждого клиента заводится отдельный поток/процесс — не годится.

NC>Код модели сервера:

NC>

NC>using System;
NC>using System.Text;
NC>using System.Net;
NC>using System.Net.Sockets;
NC>using System.Collections;

NC>namespace TestSock
NC>{
NC>    /// <summary>
NC>    /// Summary description for Class1.
NC>    /// </summary>
NC>    class Class1
NC>    {
NC>        /// <summary>
NC>        /// The main entry point for the application.
NC>        /// </summary>
NC>        [STAThread]
NC>        static void Main(string[] args)
NC>        {            
NC>                        IPHostEntry ipHostEntry = Dns.Resolve("localhost");
NC>            IPAddress ipAddress = ipHostEntry.AddressList[0];

    
NC>            ArrayList listenList = new ArrayList();
NC>            ArrayList acceptList = new ArrayList();

NC>            Socket sock = new Socket(AddressFamily.InterNetwork,
NC>                SocketType.Stream,
NC>                ProtocolType.Tcp);
NC>            sock.Bind(new IPEndPoint(ipAddress, 11000));
NC>            sock.Listen(10);
            
NC>            string msg = "hello";
NC>            byte [] bytes = Encoding.ASCII.GetBytes(msg);
NC>            while (true)
NC>            {
NC>                try
NC>                {
NC>                    listenList.Add(sock);
NC>                    Socket.Select(listenList, null, null, 1000);
NC>                    try
NC>                    {
                    
NC>                        foreach (Socket s in listenList )
NC>                        {
NC>                            Socket conn = s.Accept();
NC>                            acceptList.Add(conn);
NC>                            conn.Send(bytes);
NC>                            Console.WriteLine("Connected clients: {0}", acceptList.Count);                
NC>                        }
NC>                        listenList.Clear();
NC>                        foreach(Socket s in acceptList )
NC>                        {
NC>                            listenList.Add(s);
NC>                        }
NC>                    }
NC>                    catch(SocketException ex)
NC>                    {
                    
NC>                    }
NC>                }
NC>                catch (Exception ex)
NC>                {
NC>                    Console.WriteLine("Exception occured: {0}\nStackTrace:{1}\nPress any key to continue", ex.Message, ex.StackTrace);
NC>                    Console.ReadLine();
NC>                    break;
NC>                }
NC>            }
NC>        }
NC>}
NC>


А если попробовать перегонять в цикле из listenList в, к примеру, listenList64 по 64 сокета? ))
Re[2]: Ошибка в методе Socket.Select(...)
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 22.06.05 09:29
Оценка:
Здравствуйте, Echer, Вы писали:

E>А если попробовать перегонять в цикле из listenList в, к примеру, listenList64 по 64 сокета? ))


Просьба сокращать объемы цитирования
... << RSDN@Home 1.2.0 alpha rev. 499>>
AVK Blog
Re: Ошибка в методе Socket.Select(...)
От: BoSiC www.webview.ru
Дата: 26.06.06 17:07
Оценка:
Здравствуйте, Nickolay Ch, Вы писали:

NC>При написании проекта типа клинет-сервер возникла проблема:

NC>Сервер для обслуживания клиентов применяет метод Socket.Select(IList checkRead, IList checkWrite, IList checkError, int microSeconds);
NC>При подсоединении 64го клинента происходит обвал программы по IndexOutOfRangeException.
NC>Ниэе приведу код модели сервера(просто слушат сокет, acceptит входящие коннекты и добавляет клиентские сокеты в ArrayList checkList для прослушки):
NC>В качестве клиента использовался telnet.
NC>64ый коннект — и валится. Обвал происходит в приватном методе Socketа: SocketListTofileDescriptorSet(...)
NC>На microsoft.com глухо — ни слова об этом.
NC>Декомпильнул mscorelib, и там прям в коде прошита константа: 64 — размер входного множества для Select.
NC>Так что большее число клиентов обслужить с помощью Selecta неудасться.
NC>Даже причина этому быда найдена в хелпе по Microsoft Winsock 2 для Delphi :
NC>

NC>Four macros are defined in the header file WINSOCK2.H for manipulating and checking the descriptor sets. The variable FD_SETSIZE determines the maximum number of descriptors in a set. (The default value of FD_SETSIZE is 64, which can be modified by #defining FD_SETSIZE to another value before #including WINSOCK2.H.)

NC>Так вот — при программировании под ВинАпи можно опеределить сколько проге надо сокетов послушать. Под .Нет выходит, что нельзя.
NC>Вопрос — поделитесь кто-нить, пожалуйста опытом — как писать сервер, рассчитанный на большое число клиентов(~ неск. тысяч).
NC>Модель — на каждого клиента заводится отдельный поток/процесс — не годится.

NC>Код модели сервера:

NC>[c#]


Проблему решил? у меня такая же, поделись пожалуйста мыслями.
Спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.