![]() |
|
Модераторы: gambit |
![]()
|
|
| artstalker |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 126 Регистрация: 5.2.2009 Репутация: нет Всего: нет |
Мне надо принимать только пакеты от конкретного удалённого компа. Мне известен его ип. Как сделать, чтобы TcpListener слушал только конкретную удалённую станцию?
|
|||
|
||||
| -Mikle- |
|
|||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 1 Всего: 59 |
Если я еще не совсем потерял бдительность, то TcpListener слушает порт на "своем" компе, а не удаленные компы в принципе.
Тебе надо просто проверять адрес подключившегося компа и убивать его сокет, если адрес не тот который тебе нужен... -------------------- Если тебе плюют в спину, значит ты впереди... |
|||
|
||||
| artstalker |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 126 Регистрация: 5.2.2009 Репутация: нет Всего: нет |
TcpListener слушает на своём компе порт, но на этот порт приходят же пакеты с разных ip. Чтобы проверить адрес, мне надо начать слушать его, а для меня это не подходит. Мне нужно изначально гарантированно принимать только с одного ip
|
|||
|
||||
| -Mikle- |
|
|||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 1 Всего: 59 |
Ну во первых, сначала приходят не пакеты, а запросы на соединение. Во вторых, с каких разных? Ты же ведь будешь слушать свой порт, например 2099, чтобы туда пришел запрос на соединение, кто-то должен конкретно указать адрес твоего компа и порт (2099) как минимум. Это конечно может иметь непредвиденный характер, но таковых запросов будет не так много я полагаю. Да и даже пусть приходят, что с этого? Не разрешай им и все... Что именно тебя не устраивает? Природа сокетов не позволяет такого делать. Сокет может слушать порт (канал для соединений) на компе, и не может автоматически отвергать запросы на соединение! Решение об отвержении конекта лежит на разработчике. Ограничить доступ на какой-то порт заведомо с одного компа - это задача для файервола, который может сидеть корнями в глубинах системы и принимать решение об отвержении тех или иных запросов. -------------------- Если тебе плюют в спину, значит ты впереди... |
|||
|
||||
| artstalker |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 126 Регистрация: 5.2.2009 Репутация: нет Всего: нет |
Всё дело в том, что моё приложение предусматривает параллельный приём данных сразу с нескольких удалённых станций. Т.е. я создаю необходимое число TcpListener-ов в параллельных потоках и слушаю один и тот же порт. Если я не смогу как-то соединить каждый TcpListener с конкретным ip, то каша получится
А почему в С++ в сервисе WinSock мы можем слушать с конкретного ip? Тут нет такого аналога? Это сообщение отредактировал(а) artstalker - 6.3.2009, 21:46 |
|||
|
||||
| -Mikle- |
|
||||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 1 Всего: 59 |
Я не знаю точно, может быть там низкоуровневая реализация есть, которая отклоняет конекты. А по сабжу, теперь мне все ясно стало. Болезнь: Ты запутался в том, как все это работает. Лекарство: Всегда, всегда только один Socket может слушать какой-то порт. Когда необходимо принимать подключения, то создается слушающий сокет. При наличии в очереди запроса на соединение, слушающий сокет поступает следующим образом: 1. создает новый сокет; 2. присваивает ему какой-нибудь свободный порт; 3. возвращает тебе вновь созданный Socket; 4. продолжает слушать дальше. Все! Теперь у тебя есть эксклюзивный сокет с клиентом. Далее ты можешь проверить IP и закрыть его, если он не твой. Для теста, ты можешь дебагом посмотреть номер порта этого сокета, чтобы убедиться, что я не соврал тебе насчет номера порта, отличающегося от того, на котором ты слушаешь. TcpListener и TcpClient - это просто более высокоуровневые оболочки для Socket. Иногда с ними удобнее работать, чем с сокетом напрямую. Теперь немного кода. Ради примера, я не делал никаких потоков, а использовал таймер:
У меня был достаточно большой и достаточно сложный проект, в котором я поимел определенный опыт. Будь осторожен с многопоточностью. Если у тебя будет 200 клиентов, то создавать 200 потоков для каждого - это очень плохо кончится... Обращайся. -------------------- Если тебе плюют в спину, значит ты впереди... |
||||
|
|||||
| artstalker |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 126 Регистрация: 5.2.2009 Репутация: нет Всего: нет |
Спасибо за консультацию, теперь я начинаю понимать.
У меня к тебе пару вопросов: 1. while (tcpListener.Pending()) {} Как я понял это цикл в котором обрабатываются все запросы на подключение, после того как они обработаются цикл завершится? Просто я использую бесконечный цикл, т.к. мне надо всегда слушать порт. Может есть какой-то другой вариант.. 2.У меня не так много клиентов могут подключаться одновременно. Ну пусть будет максимум 5 штук. Может проще создать 5 TcpListener-ов в параллельных потоках и слушать 5 разных портов для каждого клиента? (это я к чему. я так понял что нельзя в параллельных потоках слушать один и тот же порт) Это сообщение отредактировал(а) artstalker - 7.3.2009, 02:39 |
|||
|
||||
| -Mikle- |
|
||||||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 1 Всего: 59 |
Да, именно так, но он снова запустится по таймеру. Забыл что ф-ия в таймере? Если никого не будет в очереди, то цикл завершится. Потом снова. Я для простоты примера так сделал, без потоков...
На сегодня других вариантов не предоставлено. Оптимально будет для этой цели сделать трединговый таймер, он использует пул потоков, вместо создания нового.
Нет, так делать не нужно. Во первых, это будет сложнее для клиентов. Они как-то должны будут еще узнать, к какому порту им подключаться. А если клиентов завтра станет шесть? Или 200? Нет, так никто не делает, потому что это не проще, а сложнее. Слушать надо только один сокет (можно в отдельном потоке), а вот обрабатывать прием/передачу отдельного сокета можно в отдельном потоке. Но не по принципу один сокет - один поток! Для начала, можно и по одному потоку на сокет, но потом обязательно переделать и реализовать динамический пул, где будет приниматься решение о необходимости создания нового потока для обработки принятых данных. Но об этом потом. Я и другие форумчане уже где-то отвечали на подобные вопросы, но мне не лень еще раз повториться. Я уже создал у себя новый проект и назвал его "artstalker". В нем я буду писать вместе с тобой. Вот тебе для начала простая архитектура, которую, мы постараемся довести постепенно до приемлемого уровня. Итак: 1. Имеется класс ClientManager. Он будет самым главным. В его задачи входит следующее: а) он создает и управляет работой TcpListener, который обрабатывает очередь запросов на подключение в отдельном потоке; б) он должен имееть поле, список подключенных клиентов. Лучше сделать словарь (Dictionary), в котором ключем будет IPAddres, а значением TcpClient. После обработки запроса на подключение в этот список добавляется клиент TcpClient. Этот список будет активно использоваться. Еще мы потом сделаем свою обертку для TcpClient (или Socket, посмотрим еще потом) и будем добавлять в список клиентов уже его, а не TcpClient; в) этот класс должен иметь методы Start(IPAddress listenAddress, int port) и Stop(), которые начинают и завершают его работу; г) должен быть метод Send(IPAddress clientIP, byte[] data) и Send(IPAddress clientIP, string data). Можно сделать оба или один из них, в зависимости от того, что ты планируешь посылать; д) событие Disconnect, которое будет вызываться если один из клиентов отвалится. В качестве параметра надо передать IPAddress отвалившегося клиента; е) событие ReciveDataReady, которое будет вызываться, когда данные от какого-то клиента будут готовы для обработки. В качестве параметра надо передать IPAddress клиента от которого готовы данные и сами данные. Для начала хватит. Можешь пока сделать только шаблон класса, то есть не наполнять его методы функциональностью. Объяви сам класс, необходимые поля в нем, методы, классы DisconectEventArgs и ReciveDataReadyEventArgs с нужными свойствами и делегаты для наших событий. Выкладывай все сюда, потом будем продолжать. -------------------- Если тебе плюют в спину, значит ты впереди... |
||||||
|
|||||||
| -Mikle- |
|
|||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 1 Всего: 59 |
Чтоб силно не заморачиваться, вот клиент, которым будем проверять наш сервер. Не проверял на практике (т.к. пока нет сервера никакого), но вроде должен работать... Потом потестируем...
Присоединённый файл ( Кол-во скачиваний: 9 )
ArtstalkerClient.rar 11,30 Kb-------------------- Если тебе плюют в спину, значит ты впереди... |
|||
|
||||
| artstalker |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 126 Регистрация: 5.2.2009 Репутация: нет Всего: нет |
Хорошо, сейчас начну писать. Давай я тогда подробнее опишу задачу и как я это вижу(и собственно как уже реализовал
Как я это вижу: 1. В приложении есть фоновый поток, который постоянно слушает порт (50174). Если к нему приходит сообщение от какого-то клиента в котом написано "#Transfer:имя_файла", то 2 Я определяю ip с которого пришло сообщение 3 Создаю новое окно в котором клиент может либо разрешить приём файла, либо запретить. В любом случае от исхода я посылаю ответ по порту 50173(т.к. 50174 должен всегда слушать, в этот момент может прийти очередной запрос на приём файла). 4 Если пользователь согласился на приём файла, то я посылаю сообщение с маркировкой "#Yes" по порту 50173(кстати тут можно было бы указать и порт на котторый будет передавать файл, но как я понял это плохой выход). 5. Начинаю слушать порт 50175(это и есть транспортный порт) 6. Удалённый компьютер прочитав по порту 50173 "#Yes" начинает отсылку файла на 50175 Собственно вчера уже реализовал, работает, но только 1 клиент - 1 сервер и немного коряво(без классов) С твоей помощью сейчас начну заново писать. Ближе к вечеру выложу класс, который ты описал Это сообщение отредактировал(а) artstalker - 7.3.2009, 15:19 |
|||
|
||||
| -Mikle- |
|
|||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 1 Всего: 59 |
Задача ясна, но видишь ты ее себе слишком запутанно.
Все намного проще - три порта не понадобятся, только один. Потом все поймешь, обещаю постараться! Ради достижения цели обучения, мы с тобой еще и собственный протокол обмена придумаем, постепенно, шаг за шагом. Добавлено через 2 минуты и 32 секунды Модераторам: Думаю ветку надо кинуть в "распределенные приложения и сеть" -------------------- Если тебе плюют в спину, значит ты впереди... |
|||
|
||||
| artstalker |
|
||||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 126 Регистрация: 5.2.2009 Репутация: нет Всего: нет |
Вот что я только что наваял
Я вот только не могу понять зачем при создании TcpListener мы передаём IP?
Я раньше создавал так
P.S. В данном случае мы реализовываем 2 отдельных приложения клиент и сервер. А мы сможем потом это объеденить в одно приложение? Суть в том, что каждое приложение может связываться со всеми другими Это сообщение отредактировал(а) artstalker - 7.3.2009, 19:41 |
||||||
|
|||||||
| -Mikle- |
|
||||||||||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 1 Всего: 59 |
Это потому, что он возвращает базовый тип EndPoint, а не IP-адрес.
Нужно наследовать от EventArgs и сделать нормальные события
По такому же принципу сделай ReciveDataReadyEventArgs. Свойствами его наделять пока не будем. Не нужна такая структура, такая уже существует: IPEndPoint
Потому что этот вариант конструктора будет убран в одной из следующих версий. Останется только два: (IPEndPoint) и (IPAddress, int)
Нет, не сможем. В данном случае мы пишем клиент-серверное приложение. Один сервер и много клиентов. Если сервер не доступен, клиенты не могут общаться между собой. Ты уж давай определяйся, а то мы уже начали с архитектуры клиент-серверного приложения. И еще я тут подумал, что так у нас ничего не выйдет. Долго это будет и не все топики информативны. Предлагаю тебе перейти на ICQ, номер я тебе скинул в PM (в самом верху страницы форума есть ссылочка "1 новых писем"). Когда будешь соединяться, в сообщении напиши что это ты, а то тут спамеров, последнее время много. Мы с тобой по ICQ отработаем весь код, и потом сюда решающим топиком прикрепим то, что у нас получится. В аське я буду через час, в 22-00 (GMT+3, Москва). -------------------- Если тебе плюют в спину, значит ты впереди... |
||||||||||
|
|||||||||||
![]()
|
| Прежде чем создать тему, посмотрите сюда: | |
|
|
Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов. Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, cully, mr.DUDA, Exception. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Распределённые приложения и сеть | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |