Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Сервер-ретранслятор на WinSock  (Прочитано 13388 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
a3design
Гость
« : 14-11-2006 09:50 » 

Ув. эксперты, у меня такая вот задача:
Есть два TCP клиента, которые могут обмениваться данными, причем обмен происходит в произвольном порядке (т.е. могут поочередно, а может быть так, что первый, к примеру, будет все время отправлять, второй только принимать и т.д.) Обмен данными идет через сервер, который просто перенаправляет сообщения от одного клиента к другому. Программист (т.е. в данном случае я Улыбаюсь ) заранее не знает, порядок обмена данными.
Подскажите как с наименьшими затратами выйти из данного положения. Нужно ли создавать по два потока для каждого клиента?

Пишу на Delphi, желателен пример на Паскале. Заранее спасибо.
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 14-11-2006 10:55 » 

Можно обойтись одним потоком, если использовать функцию select.  К сожалению, я не пользуюсь Паскалем, поэтому не могу сказать, как она представлена в Delphi.
Идея такая:
1.  сервер создаёт серверный сокет и ждёт присоединения клиентов.  После того, как оба клиента подсоединились, на стороне сервера открыты два сокета - по одному на каждого клиента.  Назовём их s1 и s2
2.  Сервер делает вызов select, в качестве аргумента передаёт массив из двух сокетов s1 и s2.
3.  select возвращает управление, если истёк таймаут или в одном из сокетов получены данные.
3.1 Если истёк таймер, то снова запустить select
3.2 если данные прибыли в s1, то получить их и отправить в s2
3.3 если данные прибыли в s2, то получить их и отправить в s1
4.  Вернуться на шаг 2

На самом деле есть ещё одно событие, по которому select возвращает упрвление: в одном из сокетов закрыто соединение.  В таком случае необходимо закрыть оба клиентских сокета и перейти на шаг 1.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
sss
Специалист

ru
Offline Offline

« Ответ #2 : 15-11-2006 01:47 » 

По одному потоку приема пакетов на одного клиента. Поток принявший пакет тут же отправляет его одному или нескольким другим клиентам сервера.

PS: Сервер на основе потоков это не есть хорошо...
Записан

while (8==8)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 15-11-2006 06:23 » 

sss, поясни, пожалуйста, а то как-то необосновано заявляешь. Я, например, с тобой в корне не согласен: TCP ориентирован на байтовый поток, а не пакетную передачу. И зачем два потока, если один прекрасно справится? Коля ведь описал процесс...
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
sss
Специалист

ru
Offline Offline

« Ответ #4 : 15-11-2006 06:55 » 

Сейчас сидел минут 15 глядел. Не знаю что сказать... Я как понял из контекста вопроса - человек использует потоковую модель. А модель на основе select это уже совсем другой вопрос. Например, почему бы не ожидать в select для 100 или 1000 клиентов? Один поток для всего сервера и все! И опять возникает разговор про пакеты. Я не понимаю - если значит мы говорим про драйвера и там употребляем NDIS_PACKET для всех блобов из сети это нормально. А если про user режим - то уже не правильно? Я же не употреблял датаграммы!
« Последнее редактирование: 15-11-2006 06:57 от sss » Записан

while (8==8)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 15-11-2006 09:24 » 

sss, да, на уровне драйверов ты работаешь с пакетами, но на уровне сокетов это уже работа с байтовым буфером, который может вместить как несколько пакетов, так и содержать непрочитанный кусок пакета. Практика показывает, что если по TCP пришел пакет, то одиночным чтением можно считать его целиком сразу (если буфер чтения достаточный), но гарантии такого поведения нет. Это как не использовать средства синхронизации в многопоточном приложении: вроде бы работает, но неожиданно сбоит.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 15-11-2006 09:27 » 

select в предложенной схеме ожидает 2 клиента, потому что так сказано в исходном посте.

В TCP на урове API сокетов действительно нет пакетов.  В одном вызове recv могут быть возвращены данные, прибывшие в одном пакете, в нескольких пакетах (то есть сегментах TCP), или только часть одного сегмента.  TCP умышленно стирает границу между сегментами и представляет данные просто как поток байтов.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
sss
Специалист

ru
Offline Offline

« Ответ #7 : 15-11-2006 09:49 » 

Ладно. Буду называть порции байтового потока блобами. Действительно, ведь несколько пакетов TCP могут собираться в один блоб и передаваться пользователю.
Записан

while (8==8)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines