При написании проекта типа клинет-сервер возникла проблема:
Сервер для обслуживания клиентов применяет метод 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;
}
}
}
}
Здравствуйте, 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 сокета? ))
Здравствуйте, Echer, Вы писали:
E>А если попробовать перегонять в цикле из listenList в, к примеру, listenList64 по 64 сокета? ))
Просьба сокращать объемы цитирования
... << RSDN@Home 1.2.0 alpha rev. 499>>
Здравствуйте, 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#]
Проблему решил? у меня такая же, поделись пожалуйста мыслями.
Спасибо.