Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2008.01.06;
Скачать: [xml.tar.bz2];

Вниз

Почему начинает подтормаживать сервер.   Найти похожие ветки 

 
DVM ©   (2007-04-24 15:12) [0]

Для примера возьмем вот такой примитивный вариант сервера. Если я запускаю параллельно скажем 50 клиентов, которые подключаются и затем отключаются от данного сервера, то, через некоторое время сервер перестает принимать подключения. Затем проходит некоторое время и сервер вновь начинает работать и так дальше циклически.

В чем проблема?

program server;

{$APPTYPE CONSOLE}
uses
 FastMM4,
 SysUtils,
 Winsock,
 Windows;

type

 ThreadData = record
   Socket: TSocket;
 end;
 PThreadData = ^ThreadData;

var
 WSAData: TWSAData;
 ListenSocket, ClientSocket: TSocket;
 Info: PThreadData;
 SockAddr: TSockAddr;
 ThreadId: THandle;
 hClientThread: Thandle;

const
 Port = word(25);

//------------------------------------------------------------------------------

procedure SocketThread(Info: PThreadData);
var
 SockName: TSockAddr;
 NameLen, OptLen: Integer;
 Buf: PChar;
 RecvSize: integer;
 s: TSocket;
 BuffSize: integer;
begin
 s := Info^.Socket;
 try
   NameLen := SizeOf(TSockAddr);
   if GetPeerName(s, SockName, NameLen) <> 0 then exit;
   Writeln(format("Client accepted, remote address [%s].", [inet_ntoa(SockName.sin_addr)]));
   OptLen := SizeOf(BuffSize);
   if GetSockOpt(s, SOL_SOCKET, SO_RCVBUF, pointer(@BuffSize), OptLen) <> 0 then exit;
   writeln(format("Receive buffer size [%d]", [BuffSize]));
   GetMem(Buf, BuffSize);
   try
     repeat
       RecvSize := recv(s, Buf^, BuffSize, 0);
       sleep(5);
       if RecvSize > 0 then
         writeln(format("Received from client: %s", [strpas(Buf)]));
     until RecvSize <= 0;
   finally
     FreeMem(Buf, BuffSize);
   end;
   Writeln(format("Client disconnected, remote address [%s].",[inet_ntoa(SockName.sin_addr)]));
 finally
   CloseSocket(s);
   Dispose(Info);
 end;  
end;

//------------------------------------------------------------------------------

begin
 Writeln("WSA Initialize...");
 if WSAStartup($101, WSAData) <> 0 then exit;
 try
   Writeln(format("Creating socket on port [%d].", [Port]));
   ListenSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
   if ListenSocket = INVALID_SOCKET then exit;
   try
     FillChar(SockAddr, SizeOf(TSockAddr), 0);
     SockAddr.sin_family := AF_INET;
     SockAddr.sin_port := htons(Port);
     SockAddr.sin_addr.S_addr := INADDR_ANY;
     Writeln("Binding socket...");
     if Bind(ListenSocket, SockAddr, SizeOf(TSockAddr)) <> 0 then exit;
     if listen(ListenSocket, SOMAXCONN) <> 0 then exit;
     Writeln("Socket status: listening...");
     repeat
       ClientSocket := accept(ListenSocket, nil, nil);
       if ClientSocket <> INVALID_SOCKET then
         begin
           New(Info);
           Info^.Socket := ClientSocket;
           hClientThread := BeginThread(nil, 0, @SocketThread, Info, 0, ThreadId);
           if hClientThread <> 0 then CloseHandle(hClientThread);
         end;  
     until false;
   finally
     CloseSocket(ListenSocket);
   end;
 finally
   WSACleanup;
 end;

//------------------------------------------------------------------------------

end.



 
Сергей М. ©   (2007-04-24 15:17) [1]


> сервер перестает принимать подключения


Это как ?
Что при этом говорит отладчик ?


 
DVM ©   (2007-04-24 15:20) [2]


> Сергей М. ©   (24.04.07 15:17) [1]

Программа сервера продолжает работать, но вот клиент подключиться не может. Спустя время - все начинает работать.

Клиент грубо говоря такой, например.


procedure TForm1.TimerTimer(Sender: TObject);
begin
 try
   IdTCPClient.Host := edtHost.Text;
   IdTCPClient.Port := strtoint(edtPort.text);
   try
     IdTCPClient.Connect;
   except
     //
   end;
 finally
    if IdTCPClient.Connected then IdTCPClient.Disconnect;
 end;
end;


Таймер на 300 Мсек.


 
DVM ©   (2007-04-24 15:23) [3]

Да, еще если сервер закрыть и запустить вновь, то проблему это не решает. Если до закрытия он не подключал клиентов, то и после поторного запуска то же самое. Спустя минуту все само восстанавливается.


 
Сергей М. ©   (2007-04-24 15:26) [4]

Ну тогда, если отладчик тебе не указ, давай погадаем на кофейной гуще)


 
DVM ©   (2007-04-24 15:32) [5]


> Сергей М. ©   (24.04.07 15:26) [4]

Я извиняюсь, но причем тут отладчик? Ведь ни исключений ни ошибок никаких в самом сервере не возникает. На что смотреть то?

Клиент же не может подключиться. У инди в данном случае генериться исключение Socket error 10048, Adress already in use


 
Сергей М. ©   (2007-04-24 15:39) [6]


> Клиент же не может подключиться


Что, прямо так и говорит, мол, "не могу" ?


> У инди в данном случае генериться исключение Socket error
> 10048, Adress already in use


Чавой-то ?

Ф-ция accept() НЕ может вызвать такой ошибки.

Ее можно увидеть в рез-те вызова bind и connect, но никак не в рез-те accept, listen, closesocket.


 
DVM ©   (2007-04-24 15:44) [7]


> Ф-ция accept() НЕ может вызвать такой ошибки.

Где я написал, что это исключение появляется в результате вызова Accert?????? Сервер работает!

Это исключение появляется в клиенте на Инди. Да бог с ним с инди. Из телнета я подключаюсь к серверу - получаю олуп: Не могу установить соединение. Через некоторое время минута-две все замечательно начинает работать.

Вы не ставьте все с ног на голову, а прочитайте мой вопрос от начала и до конца.


 
DVM ©   (2007-04-24 15:50) [8]

Проблемы возникают только если долбить сервер массой клиентов очень быстро. Что это? Особенность операционной системы?


 
Сергей М. ©   (2007-04-24 16:18) [9]


> Это исключение появляется в клиенте на Инди


Ну а какого же черта ты пеняешь на сервер, который, якобы, "не может" ?)


> Вы не ставьте все с ног на голову


Я-то как раз не ставлю.

Ставишь именно ты, замесив свои проблемы в жуткую кашу и не желая воспользоваться отладчиком хотя бы на стороне клиента.


 
DVM ©   (2007-04-24 16:25) [10]


> Ну а какого же черта ты пеняешь на сервер, который, якобы,
>  "не может" ?)

Так он действительно не может подключать более клиентов. А клиент будь то на инди, будь то телнет или другой какой об этом лишь сообщает.


> Ставишь именно ты, замесив свои проблемы в жуткую кашу и
> не желая воспользоваться отладчиком хотя бы на стороне клиента.
>

Где здесь жуткая каша? Отладчик на стороне клиента бесполезен абсолютно, т.к. также ведет себя и телнет в качестве клиента.
Результаты функций WinSock я и без отладчика все посмотреть могу.

Если не секрет, расскажите мне темному, где и каким боком я тут могу приложить отладчик и для выяснения чего?


 
Сергей М. ©   (2007-04-24 16:29) [11]


> где и каким боком я тут могу приложить отладчик и для выяснения
> чего?
>


Ставишь брейкпойнт на строчку с вызовом accept - и вперед с песней !


 
DVM ©   (2007-04-24 16:38) [12]


> Сергей М. ©   (24.04.07 16:29) [11]


> Ставишь брейкпойнт на строчку с вызовом accept - и вперед
> с песней !

Если учесть тот факт, что строчка accept будет выполнена
50 клиентов * 3 подключения в сек. * 60 сек (ср время до возникновения проблемы) = 9000 раз. То данный способ малоэффективен.


 
Сергей М. ©   (2007-04-24 16:41) [13]


> DVM ©   (24.04.07 16:38) [12]


Ты в [6] вник ?


 
Сергей М. ©   (2007-04-24 16:46) [14]


> 50 клиентов * 3 подключения в сек. * 60 сек (ср время до
> возникновения проблемы) = 9000 раз


Прямо DDoS-attack какая-то)


 
DVM ©   (2007-04-24 16:59) [15]


> Ты в [6] вник ?

Там вникать не во что, все написанное там мне ясно было и раньше. Мне кажется, мы недопонимаем оба друг друга.

Мне хочется разобраться - данное поведение связки клиент + сервер + XP -это какие-то ошибки в моем коде (в данном случае это скорее всего код сервера) или это нормальное поведение операционной системы в связи с устраиваемой мной действительно Dos атакой.

Еще раз хочу подчеркнуть, что сервер работает нормально. Никаких исключений не выдает. Прекрасно подключает и обслуживает разумное число клиентов неограниченное время. Клиенты (на делфи или другие какие - неважно) тоже без проблем подключаются к серверу и отключаются.

Но я продолжаю увеличивать число клиентов и частоту их запросов. Через некоторое время сервер (или не он, а Winsock) начинает подтормаживать. Это проявляется в том, что подключения клиентов на сервере сначала регистрируются реже, потом еще реже и наконец перестают регистрироваться вообще. Т.е. эта самая пресловутая accept() не возвращает управление потоку. Ничего не происходит. На клиентах вылезают ошибки подобные Socket error 10048, Adress already in use
Через некоторое время (1-2 минуты) нормальная работа и клиентов и сервера постепенно возобнавляется и через некоторое время все опять работает замечательно. Далее опять начинает замедляться и т.д.

Такое ощущение, что исчерпывается лимит каких то автоматом освобождаемых сетевых ресурсов, которые сразу не освобождаются при разрыве связи.


 
Сергей М. ©   (2007-04-24 17:12) [16]


> На клиентах вылезают ошибки


"Вылезают"  - рассуждения дилетанта.

Берешь отладчик (либо внедряешь протоколирование) и выясняешь, какая конкретно ф-ция при каких условиях вызывает этот отказ.

А вызвать его на стороне клиента может либо bind либо connect - тебя что, ткнуть носом в справку или сам сподобишься убедиться ?)


 
DVM ©   (2007-04-24 17:20) [17]


> "Вылезают"  - рассуждения дилетанта.

Язва Вы все таки Сергей :) Вот писал слово это "вылезают" и думал - ведь и к нему придерется - так и есть:)


> Берешь отладчик (либо внедряешь протоколирование) и выясняешь,
>  какая конкретно ф-ция при каких условиях вызывает этот
> отказ.

Да я этим и займусь. Просто думал может кто сталкивался с подобным и ответ на поверхности лежит. С отладчиком трудно будет, лучше протоколирование уж.

> А вызвать его на стороне клиента может либо bind либо connect
> - тебя что, ткнуть носом в справку или сам сподобишься убедиться
> ?)

Ну bind на стороне клиента не вызывается в данном случае, а вот connect да.


 
Сергей М. ©   (2007-04-25 08:15) [18]


> bind на стороне клиента не вызывается в данном случае


Почему ты в этом так уверен ?
BoundIp/BoundPort явно устанавливаются тобой ?


 
SpellCaster   (2007-04-25 11:10) [19]

> С отладчиком трудно будет, лучше протоколирование уж.

В чём затруднени? Запусти клиент из-под отладчика, дождись, пока сервак не перестанет принимать коннекты, и уже тода ставь брейкпоинт. Правда, я тоже не понимаю, каким боком тут поможет отладчик - саму-то функцию connect не оттрассируешь, а что она возвратит ошибку.ю можно и так увидеть, без отладчика...



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2008.01.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.005 c
15-1196715422
барбос в тапочках
2007-12-03 23:57
2008.01.06
анимэ


2-1197204719
azl
2007-12-09 15:51
2008.01.06
ORDER BY (Query1.Edit) Cannot modify a read-only dataset


15-1196791428
@!!ex
2007-12-04 21:03
2008.01.06
Драйвер на Windows 2003 Server


2-1197161141
O.Snopok
2007-12-09 03:45
2008.01.06
Как приостановить выполнение процедуры до изменения Clipboard


2-1197056115
AntiPupkin
2007-12-07 22:35
2008.01.06
Перечислить ID потоков в открытом процессе





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский