| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > .NET для новичков > Обмен сообщениями клиент-сервер |
| Автор: V0fka 15.2.2014, 17:37 |
| Привет! Что нужно сделать. На сервере крутится программа, которая принимает входящие подключения от клиентов и при возникновении определенного события - отсылает им сообщения. Клиенты принимают сообщения и как-то реагируют. Клиентов планируется на данном этапе порядка 100. 1) Сервер: Сервер был сделан с помощью класса TcpListener. Далее в бесконечном цикле вызывается его метод AcceptTcpClient() и после полученный TcpClient добавляется в коллекцию clients. Это происходит не в основном потоке. Для отправки сообщений в цикле обходится коллекция clients и для каждого элемента выполняется io = client.GetStream() и потом io.Write(...); 2) Клиент: Используется класс Socket. В бесконечном цикле выполняется метод Receive и тут же эти данные обрабатываются и выполняются какие-то действия. Это происходит не в основном потоке. ///////////////// Я не особо шарю с C#, поэтому хотелось бы получить совет от людей, которые шарят, правильно ли выбрано направление для решения этой задачи: 1) Те ли классы я использую для сервера и клиента? 2) Если одновременно к серверу будет подключаться несколько клиентов, то используя в бесконечном цикле AcceptTcpClient() - я не пропущу никого из них? 3) Правильно ли на клиенте я "слушаю" сообщения? Меня смущает бесконечный цик там. Возможно это так делают, просто хочу узнать. Если же нет, то подскажите, пожалуйста, как надо. На данном этапе в детали не вдаюсь, т.к. вопросов тысяча. Просто хочу узнать правильное направление, чтобы когда уже будет виден финиш не обломиться из-за того, что в начале что-то не так было сделано. Спасибо! |
| Автор: V0fka 19.2.2014, 12:25 | ||||||
А какое преимущество TcpClient-а, в данном случае, будет?
Ясно, спасибо!
Правильно я вас понял, асинхронно - это, например, так: http://cyber-blog.klan-hub.ru/2010/08/28/асинхронная-работа-с-сокетами-в-c-шарп/ ? Если да, то у меня здесь появилась проблемка. В классе Server я подключенных клиентов собираю в коллекцию:
и у меня возникает ошибка, как здесь: http://forum.vingrad.ru/forum/topic-336459.html: Для нестатического поля, метода или свойства "System.Windows.Threading.Dispatcher.Invoke(System.Delegate, params object[])" требуется ссылка на объект. Я её решил, передавая экземпляр Dispatcher в объект класса Server и соответственно вызываю Invoke через этот переданный диспатчер. Но, как всегда, есть сомнения насчет применения такого подхода. Хотелось бы получить "благословение" либо пинок в нужную сторону от знающих |
| Автор: jonie 19.2.2014, 14:05 |
| а зачем связывать очередь с UI ?! |
| Автор: V0fka 19.2.2014, 16:38 |
| Сервер - это WPF приложение. На форме есть ListView, к которому биндится очередь и видно кто подключен сейчас. |
| Автор: jonie 19.2.2014, 17:52 | ||
и чО? Очередь просто должна уметь уведомлять подписчиком что что-то поменялось, а те уже в своих обработчиках должны решать как на эти действия реагировать - плохая идея добавлять данные в UI потоке. |
| Автор: V0fka 21.2.2014, 10:07 | ||
Я по вашему совету переделал сервер и клиент с использованием асинхронных методов. Конкретно сервер работает через AcceptAsync(...). И в результате когда хочу в коллекцию (а это ObservableCollection) добавить элемент, то Visual Studio говорит, что "нельзя добавить из этого потока" (ошибка не дословная, но я думаю, вы поняли что это). Тогда я нагуглил, что нужно добавлять через Dispatcher.Invoke. Попрбовал, но получил ошибку, которую выше озвчучил. После этого сделал так, как написал.
Можете пример какой-то привести, как это на примере WPF делается? |
| Автор: V0fka 21.2.2014, 11:19 |
| По ходу разбирательств возник новый вопрос. Есть на сервере коллекция подключенных клиентов. В цикле обхожу её и методом Send хочу отправить сообщение. Все классно работает, если клиент подключен. Но если он отключен, то сервер виснет. Начал искать решения: 1) Установил на сервере в Socket.SendTimeout = 1, сделал через try catch отправку и если код попадает в catch - то клиент из коллекции удаляется. Подскажите, можно ли так делать, если планируется около 100 подключенных клиентов? 2) Обхожу коллекцию. Проверяю статус клиента IsConnected. Если IsConnected = false, то удаляю элемент из коллекции, если true, то отправляю сообщение. Но тут я заметил, что между проверкой и отправкой сообщения этот статус может поменяться и получается, что в момент Send клиента уже нету. Вопрос: как правильно проверять активных клиентов, чтобы им дошли сообщения? |
| Автор: jonie 21.2.2014, 12:26 |
для .net 4.5 имеется http://msdn.microsoft.com/en-us/library/hh140164.aspx, а для других версий можно написать свою коллекцию же, с маршалингом вызовов callback делегатов в нужном SyncronizationContext-е. |
| Автор: V0fka 21.2.2014, 15:24 |
| jonie, очередной раз я вам признателен за ответ, но что делать с BindingOperations.EnableCollectionSynchronization я в упор не пойму. Был бы очень признателен за примеры кода (псевдокода). |