Найпростіший чат на idTCPServer
Для чату буде виділений сервер і купа клієнтів. Питання: для клієнта потрібно буде обидва компоненти - idTCPClient (для передачі) та idTCPServer (для прийому)? Або якось можна встановити idTCPClient в режимі очікування вхідних повідомлень? Якщо я все правильно зрозумів, то не можна.
подивися, як це зроблено в прикладах Indy (IndyDemos\Chat\Client)
хе там стоїть таймер на півсекунди, в ньому робиться readln з таймаутом 5 мс. тобто, повідомлення надходитимуть із затримкою максимум 0,5 сек. для мене неприйнятна така затримка, та й не хочу тримати потоки відкритими, тому що клієнтів передбачається дуже багато. Поки що зупинився на ідеї ставити кожному клієнту за idTCPServer"у.
> поки що зупинився на ідеї ставити кожному клієнту > idTCPServer"у.Більше безглуздої ідеї придумати не можна. Чим тобі не подобається стандартний механізм? Після моменту з'єднання перестає існувати таке поняття як клієнт і сервер. Є встановлене з'єднання, в обидва кінці якого ти можеш надсилати та приймати дані.
Так, але як це реалізувати на TIdTCPClient? У компоненті TTCPClient є подія OnReceive, а в TIdTCPClient - ні. Доводиться ставити таймер і робити ReadLn із таймаутом. Плюс до цього доведеться ставити TIdAntiFreeze, щоб при цьому програма не підвисала. При цьому повідомлення клієнту надходитимуть з дискретністю таймера. Невже так і роблять? Чи є спосіб краще?
Абстрактне питання: а чому тебе не влаштовує інтервал у півсекунди?
для чату в локальній мережі з інтерактивними іграми (вікторина, мафія та інші) півсекунди – це дуже багато.
ну постав 100 мсек.
По-перше: що писати в обробнику таймера? ReadLn? А якщо клієнтові надійшло 2 повідомлення? Тоді другий він отримає надруге спрацювання таймера? А якщо йому 100 рядків із буфера відправили? Він їх 10 секунд отримуватиме? По-друге: не люблю відкриті з'єднання. Вони вантажать від сервера, та й глюк з ними такий: якщо комп'ютер клієнта повис, то з'єднання ЗАЛИШАЄТЬСЯ ВІДКРИТИМ. Доводиться вводити додаткову команду ping. А якщо клієнту прийде повідомлення після зависання, але до пінгу, то взагалі глюки починаються (у мене через це прога-сервер вилітає). так що найлогічніший вихід ставити TIdTCPServer. Якщо у кого є зауваження, поправте мене.
А якщо йому 100 рядків із буфера відправили?А якщо йому 100 рядків відправили, то роби ReadLn у циклі до першого порожнього рядка. На час обробки отриманої відповіді відключай таймер. Обробив прийняту команду - знову вмикай. Більше вигадки і твої проблеми розсмоктуються.не люблю відкриті з'єднання.Не люби. Але твій задум з серверним компонентом на клієнті для чатових повідомлень має недолік: сервер не зможе відкрити коннект до такого клієнта для передачі чергового повідомлення, якщо клієнт знаходиться під проксі. заважає мати ще один компонент для специфічних завдань. зависання, але до пінгу, то взагалі глюки починаються (у мене через це прога-сервер вилітає). ситуації.Плюс до цього доведеться ставити TIdAntiFreezeА чим тобі TIdAntiFreeze не подобається? Зручний компонент, знімає основну проблему приблокуючий режим.
значить так .. негайно дуй сюди http://book.itep.ru читай-вникай до повного просвітлення в частині TCP-протоколу та Winsock
бо те, що ти стверджуєш - нісенітниця
у мене майже така сама проблема.
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread); var s,sIP,sCommand1,sCommand,sOldNick,sNewNick: string; i,k:integer; a:IPNames; begin try sCommand:=AThread.Connection.ReadLn; sIP:=AThread.Connection.Binding.PeerIP; If length(sCommand)>0 then BeGiN . . . EnD; except begin Append(FLogs); Writeln(FLogs," Exception on Server.Execute "+sIP+": "+sCommand); CloseFile(FLogs); IdTCPServer1.ThreadMgr.ReleaseThread(AThread); end end; end;
Іноді чат по півдня бігає без проблем, іноді кожні півгодини висне. У мене скрізь йде запис у логі, і перша помилка завжди йде звідси. Потім з'являються повідомлення про помилки в інших місцях.
Кому не ліньки, надішліть, будь ласка, приклад IndyDemos\Chat на [email protected]. Я на 6 дельфі сиджу, там його немає.
Що ти мучишся. Використовуйте компоненти ICS (http://www.overbyte.be). Краще компонентів для роботи із мережею не зустрічав. Indy теж непоганий. але в певних речах. Я досить багато писав під ці компоненти. Можна з легкістю реалізувати багатопотоковий сервер, який буде чудово справлятися із завданнями та обробляти дані максимально швидко, у міру надходження даних від клієнтів.
Я свого часу, коли починав писати свій чат, вибирав на якій основі його робити, або своїми руками через API сокети. Або використовувати готовий компонент. Дійшов висновку, що не варто винаходити велосипед у цьому випадку. Перепробував багато компонентів. І зупинився на ICS як найбільшпродуманому та зручному у використанні та адаптуванні до конкретного проекту. І не шкодую. Компонент просто відмінний (це я про TWSocket) та реалізацію сокетів від ISC. Тим більше в поставці компонента йде безліч прикладів на всі випадки життя. Крім того, він постійно оновлюється + FWS.
versНе зрозумів питання. А навіщо idTCPClient ставити в режим очікування? Використовуй idTCPServer, він для цього і зроблений! 2 сеунди відпустити Enter при надсиланні повідомлення) через розсинхронізацію. idTCPServer чудово підтримує багатопоточність. Синхронізувати з процедурою-процесором можна одним м'ютексом (подією/критичною секцією).
> для клієнта потрібно буде обидва компоненти - idTCPClient (для > передачі) та idTCPServer (для прийому)?
навіщо обидва ? idTCPClient - це кл.частина з'єднання, idTCPServer - серверна, що випливає хоча б з назви
та та інша частини "вміють" і передавати та приймати дані
саме суворо навпаки - зазвичай таки тримають, бо під "звичайними" чатами (яких туєва хуча в мережі) маються на увазі чати, що використовують http. http ж є прикладний протокол, що базується на транспортному TCP-протоколі, який передбачає (!) постійне з'єднання між клієнтом та сервером
> ініціалізувати з'єднання TCPServer"ом якщо і можна, то це збочення
>> ініціалізувати з'єднання TCPServer"ом якщо і можна, то >>
можна ініціювати з'єднання від TCPServer"а до сервера :)
мається на увазі ситуація, коли один TCPServer стає клієнтом іншого TCPServer?
нісенітниця.штатної реалізації це неможливо, бо або connect() або bind()+listen() .. але ніяк не те й інше одночасно
соррі, зглючил :) поглянув у вихіднику, там програма-сервер створює динамічно клієнта для коннекта до сервера, що стоїть вище.
во ! це зовсім інший коленкор) і саме з цього коленкора пошиті чи не всі додатки, що реалізують хоча б ф-ції того ж проксі-сервера
А в цьому питанні, як мені здається, йдеться про LAN чаті, які рідко базуються на http-я не зустрічав.
я говорив про LAN-чат ясна. :) теж роблю динамічне створення idTCPClient.