Автор Тема: Perl recv  (Прочетена 1591 пъти)

PERMANENT

  • Напреднали
  • *****
  • Публикации: 94
    • Профил
Perl recv
« -: Feb 25, 2007, 21:53 »
Как мога да определя за колко време да е отворен даден сокет?Ползвам
модула IO::Socket но ще са ми полезни и примери които ползват и други методи.
Активен

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Perl recv
« Отговор #1 -: Feb 26, 2007, 11:38 »
Не съм perl-аджия, но предполагам нещата стоят по сходен начин при C.

Какво разбираш под "колко време е отворен" сокета? Сокета blocking или non-blocking е? Искаш да разбереш дали отсрещната страна е затворила връзката или дали tcp сесията е timeout-нала? Въобще за tcp сокет ли става въпрос, защото при udp сокетите нещата са доста различни и трудно може да се говори за "затваряне" на връзката или за таймаут-ване, просто протокола не е connection-ориентиран.
Активен

"Knowledge is power" - France is Bacon

PERMANENT

  • Напреднали
  • *****
  • Публикации: 94
    • Профил
Perl recv
« Отговор #2 -: Feb 26, 2007, 14:37 »
Направо ще пиша каква точно ми е цулта за да бъде ясно.
Почнах да пиша една програма на perl tk в която ще е включен доста примитивен чат.Но за да се визуализира някакъв прозорец трябва да се изпълнява MainLoop и ако поради някаква причина това спре да става всичко се омазва докато цикала не продължи.Точно за това не мога да се впускам в дълги чакания на пакетите.Единственото което можах да измисля е за стотни от секундата да се отваря сокет които да получава идващите пакети и ако не е пристигнал никакъв пакет тои сам да се затвори за да може да се изпълни mainloop-а.Не съм сигурен че така ще стане нещо но от опит нищо не се губи.Използвания протокол е udp но ако това не е възможно да стане при него направо убеси за tcp-то.

Виждам че разбираш от C и искам да те попитам дали има някакъв начин един процес да стартира други свои под процеси които да се изпълняват паралелно и изходния им поток от данни да се буфелира за да могат тези данне да се обработват във всеки един момент от главния процес.Въпроса ми е конкретно за C и отговор от рода на
'да/не' би ми свършил работа
Активен

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Perl recv
« Отговор #3 -: Feb 26, 2007, 16:24 »
Оооо ами забавно. UDP-базиран чат сървър ще е голяма занимавка според мен, нямаш формално установяване и затваряне на сесия, прекалено много неща ще трябва да мислиш, а от гледна точка на сигурност и стабилност нещата придобиват грозен характер.

За да ползваш udp протокола, трябва да имаш идея за следните неща:

1) кога една комуникация се счита за "установена" - т.е предполагам не искаш за всеки идиот, който ти пусне един UDP scan да речем, да асоцираш разни структури и да заделяш обем памет (в C). Това ще ти трябва и при положение че пазиш някаква таблица с "клиенти", навързани към сървъра
2) Кога една комуникация се прекратява. Може да си дефинираш някаква команда в твоя чат протокол, но какво става ако отсрещната страна затвори клиента, преди да я изпрати, вечно ли ще стои в таблицата от клиенти, или след даден timeout период ще се счита за "разкачена"? Ако има такъв timeout, дали няма да има вариант да "разкачаш" клиенти, които просто не пращат продължително време нищо, без да са затворили клиента?
3) По какъв начин ще различаваш клиентите си, ако имаш 10 клиента зад НАТ примерно (трябва ти да си следиш и source port)
4) Колко е ефективна такава комуникация, нямаш гаранция, че отсреща нещото ще се получи или не, трябва да имплементираш някакъв механизъм, който да осигурява потвърждения на приетите данни. Накрая като нищо можеш да завършиш, преоткривайки топлата вода (т.е TCP протокола '<img'>  )

Иначе при tcp-базираните "server" sockets има няколко варианта какво да правиш след socket()/bind()/listen()/цикълът с accept():

1) За всеки нов сокет, fork()-ваш нов процес, който комуникира само с този сокет, който е върнат от accept(). Това е модела в ранните apache-ta, както и все още на доста приложения (postgresql например). Според мен това е най-тъпия вариант: представи си 100 едновременни клиента, за които вдигаш нови процеси, имаш много кофти context switch-ове, load average, който ако не е 100, то ще е поне 10-20-30, разхищение на памет, тъпотия.

2) За всеки нов сокет, вдигаш една нишка с pthread_create(). Този вариант е доста по-бърз от първия, защото нишките споделят обща памет и ресурси и почти няма копиране на данни в паметта между нишките, но въпреки това, един такъв сървър пак няма да може да понася големи натоварвания. Въпреки това, този метод е изключително разпространен.

3) Обработваш всички accept()-нати сокети в рамките на един процес/нишка. Това се постига с разни polling механизми, като има поне 2 варианта - poll()/select() и epoll-базиран. select() е бавна работа, обхожда се в ядрото един масив за всеки сокет и вади лоша производителност при голям брой клиенти. epoll нещата обаче са доста бързи, по-бързи от всичко останало (в това число прехваления kqueue на FreeBSD). Има и някакви варианти с RT сигнали, но не ги знам.

Проблемът там е че това нещо не е скалируемо - ако имаш няколко процесора, твоят сървър може да се изпълнява само върху един процесор в един определен момент, така че и 8-процесорна машина да си вземеш, няма да има почти никаква разлика с еднопроцесорна. Отделно, трябва да се пише много внимателно, защото една грешка ще съсипе цялото приложение, не определен процес или нишка.

4) Смесен вариант - до неотдавна имах манията да си пиша HTTP load-balancer, като реших да ползвам някаква бройка workthreads със собствени epoll sets. Като идея е прекрасно, би трябвало това да е най-добрата софтуерна архитектура, обаче поради некадърни locking механизми, това моето нещо когато го докарах до работен вариант, не можеше да държи повече от 100-200 едновременни конекции (apache backend-ите, сами по себе си държаха повече, хаха). Това е най-добрият вариант, но очевидно трябва да се пишат нещата вече наистина много внимателно - освен проблемите присъщи на еднонишковите event-based модели (epoll), това придобива и проблемите на многонишковите приложения, там конкурентност, мутекси, глупости. Ако си добър програмист, това вероятно е най-добрият вариант, но аз явно далеч не съм такъв '<img'>

И сега като финал, замисли се за сигурността на един UDP сървър: нямаш sequence numbers, а подправянето на udp пакети е изключително лесно. С hping3 примерно можеш лесно да правиш UDP floods със случайни подправени източници и съдържание на пакетите. Замисли се докъде може да доведе това нещо твоето приложение '<img'>


П.П. търси в гугъл за "c10k" в момента в който направиш нещо работещо и искаш да го изпипаш и оптимизираш като хората '<img'>



Активен

"Knowledge is power" - France is Bacon

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Perl recv
« Отговор #4 -: Feb 26, 2007, 16:44 »
А, да и за блокиращите/неблокиращите сокети, значи има 2 варианта:

1) blocking socket. Когато викнеш recv()/read()/там с квото четеш от сокета, ако няма пристигнали данни, целият процес "спи" докато се появят такива. Ако ползваш някакъв polling механизъм предполагам ти е ясно че не е приемливо програмата ти да чака нещо от един сокет, и докато не дойде, всичко останало да е на заден план. Така по никакъв начин не се постига добра производителност

2) non-blocking socket - когато четеш от сокета обикновено или ти се връща бой прочетени байтове или някаква грешка (при TCP сокети грешката може да означава и че сокета е "затворен", което е прекрасно). Това обаче налага малко усложнение в кода, защото понякога изчиташ 0 байта от сокета (просто няма нищо пристигнало) и не е хубаво да го отебаваш. Или пък точно в момента е пристигнала част от съобщението, трябва да имаш механизъм да го буферираш и да чакаш останалата част (ебахти не знам как стои въпроса с UDP, но там дори може и да не пристигне и нямам идея какво се прави). Ако въобще мислиш да ползваш нещо event-базирано, винаги прави сокетите не-блокиращи, в противен случай цялата идея се обезсмисля. Ако все пак се наложи да правиш цикъл, в който четеш от non-blocking сокет, докато не пристигне нещо,  също внимавай: слагай поне малко nanosleep()/usleep(), в противен случай тормозиш процесора и не даваш възможност друг процес/нишка да се schedule-не отгоре.

А иначе така както си го замислил да праскаш един сокет да четеш/пишеш от някой клиент "за малко" няма да стане, просто е голяма глупост. Не знам в perl, но в C има функции recvfrom/sendto, с които можеш да пишеш/четеш от даден peer. Въпреки това, този начин, който си избрал е глупав и изключително предразположен към грешки, надявам се да не се обидиш де '<img'>

Защо не го реализираш върху TCP протокола, ще е по-лесно според мен?



Активен

"Knowledge is power" - France is Bacon

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Perl recv
« Отговор #5 -: Feb 26, 2007, 17:05 »
Оффф съжалявам че съм толкова многословен, ама темата ми е присърце. Пак казвам че не знам за perl, но за C има една библиотека, libevent, която доста улеснява polling (event-based) обработката на клиентски сокети. Предполагам че си има и perl wrapper, наистина е удобно нещо, макар че не съм се занимавал усилено с нея. Има предефинирани различни протоколи отгоре, въобще забавно нещо е, на пръв поглед доста улесняващо.

Единственият й проблем (в момента) е че наскоро излезе някакъв бъг в парсването на това дето идва от DNS сокетите, та ако ще я ползваш примерно да правиш reverse resolving на клиентите си, по-добре недей. Но наистина, от това което съм гледал е доста удобно нещо и спестява немалко работа, няма да се занимаваш с разни epoll sets и директно можеш да си дефинираш callback функции дето се изпълняват примерно при получаване на данни или затваряне на сокета. Освен това спестяваш и частта с буферирането на "полу-пристигналите" данни.
Активен

"Knowledge is power" - France is Bacon

PERMANENT

  • Напреднали
  • *****
  • Публикации: 94
    • Профил
Perl recv
« Отговор #6 -: Feb 26, 2007, 19:15 »
Намерих един модула Coro::Socket и с него лесно се създават non blocking socket а явно точно това ми трябва.Мерси много за помоща
Активен

Подобни теми
Заглавие Започната от Отговора Прегледи Последна публикация
Perl
Общ форум
x11r6 5 3589 Последна публикация Aug 09, 2003, 10:03
от x11r6
Perl
Общ форум
Йордан 3 3032 Последна публикация Nov 13, 2003, 16:14
от Йордан
Gtk-Perl
Хардуерни и софтуерни проблеми
apogza 0 1944 Последна публикация Jan 24, 2004, 12:52
от apogza
Ползва ли се Perl в България и за какво?
Общ форум
berov 63 19306 Последна публикация Jan 31, 2005, 11:17
от toxigen
Четене от Серийни портове с Perl
Общ форум
berov 2 2768 Последна публикация Jun 15, 2004, 18:17
от berov