![]() |
Правильная организация Server<-> client
Как правильно реализовать обмен данных между сервером и клиентом при условии, что клиентов несколько (4 штуки максимум) и сервер постоянно что-то должен выполнять (т.е не должно быть блокировки)?
Само детище на C# и как я понял в тренде сейчас async/await ,но я не знаю как это использовать, a не круто делать так: * Поток регистрации клиентов * Поток логики * По-потоку на каждого клиента Еще желательно, что бы CPU-frendly это все было, так как десктопная приложенька, которая предполагается, будет работать фоном. Тыкните в правильное направление. |
Ответ: Правильная организация Server<-> client
Почему «не круто» делать через потоки?
|
Ответ: Правильная организация Server<-> client
Цитата:
![]() Какого фига все, что после обведенного красным НИКОГДА не выполняется?? Я ради эксперимента даже использовал обычный метод, и все равно, даже в дебагере дальше этого места не идет, и главное нету исключений вообще никак. Асинхронная запись работает, а асинхронное/синхронное чтение НЕТ! |
Ответ: Правильная организация Server<-> client
Я не особо по асинхронности, но сейчас сделал по примеру в мсдн и всё работает.
![]() |
Ответ: Правильная организация Server<-> client
Цитата:
У меня TcpClient.Stream, писаться в него пишется, а читаться - нифига. :wild: ![]() |
Ответ: Правильная организация Server<-> client
Оказалость, что если указать локальным хостом для TcpListener "127.0.0.1", то можно словить забавный баг - до него нельзя достучаться по IP локальной сети, у меня это 192.168.1.3, а если получается, то только сервер не может из него читать - только писать.
|
Ответ: Правильная организация Server<-> client
Цитата:
Однако создавать по потоку на каждого клиента - это самый плохой способ. Большую часть времени потоки будут тупо ничего не делать а ждать данных от i/o. В итоге будут жрать память и жрать процессорное время. Короче херовая масштабируемость. Впрочем, если там 3-4 клиента то разница вообще незначительная. Цитата:
|
Ответ: Правильная организация Server<-> client
Чтение с клиентов данных и их подготовка (десериализация) к употреблению в игровом цикле. Это одним потоком с использованием async/await.
Игровой цикл в своём потоке, выполняется фиксированное раз в секунду. Чем выше частота логики, тем лучше (обычно), но и CPU стоимость будет выше. Цикл рассылки данных, может быть по той же частоте как и игровая логика, а может быть реже в два раза. Зависит от ситуации. Но должен выполнятся также конкретное раз в секунду, и сразу же после игрового цикла. Собирает данные с игрового цикла, и рассылает всем клиентам используя async/await. Использовать поток на каждого клиента - не масштабируется, и жрёт много RAM'а, также усложняет всю логику синхронизации данных между потоками. |
Ответ: Правильная организация Server<-> client
Цитата:
Сменил IP на 0.0.0.0 вместо 127.0.0.1 - все работает. Цитата:
Пусть у нас 4 клиента, шаг опроса -10 ms , сделаем до каждого асинхронный запрос на чтение данных, а придет он только через 10 + ping. У меня сейчас Один поток логики с Thread.Sleep(10), который асинхронно обрабатывает подключение, которое асинхронно запускает цикл чтения у подключившегося клиента (кароче, поток фактически запускает). Это асинхронное чтение десериализует и вызывает делигат с получеными данными, на который подписан поток логики. Вроде работает, только не могу с входного потока прочитать, не закрыв его:wild:. Вернее, у меня клиент на Java. Хоть очищай, хоть не очищай выходой поток - пока его не закроешь (что нельяз, так как закроется сокет) - данные не уйдут:wild: в c# это решилось Writer.autoFlush, а у BufferedWriter в Java такого нет и flush не помогает. |
Ответ: Правильная организация Server<-> client
Я с Java работал лет 6 назад, и как раз работал с потоками и веб сокетами, там есть возможность опрашивать есть ли в наличии для чтения данные из сокета, и затем получать если есть, совмещаешь это с асинком и будет ок.
Гугли. |
Ответ: Правильная организация Server<-> client
|
Ответ: Правильная организация Server<-> client
Цитата:
|
Ответ: Правильная организация Server<-> client
Топикстартер, ты что - переделал первый пост? Когда я читал его первый раз, там была фраза, что мол, потоки плохо без особой мотивации - что и вызвало недоумение.
Вообще - солидарен с mok-иной архитектурой. Вроде ещё механизм "пул потоков" по теме может пригодиться, но я с ним не работал. |
Ответ: Правильная организация Server<-> client
Цитата:
|
Ответ: Правильная организация Server<-> client
Судя по всему в этой теме смешалось в кучу все: кони, люди, потоки, таски, async/await, threadpool...
Тебе надо - создать таск который в бесконечном цикле принимает соединения. Когда принимаешь соединение создаешь таск с бесконечным циклом в котором принимаешь данные. Далее есть 2 варианта - если у тебя архитектура запрос/ответ (ну как http примерно) то сразу же начинаешь обрабатывать. Если у тебя что-то типа реалтайм сервера, то ты полученные данные просто куда-то кладешь (в какое-то потокобезопасное хранилище). Нету никакого "шага" в виде 10мс на чтение. Читаешь сколько можешь. Вот на обработку (если мы говорим о реалтайм сервере) уже может быть шаг предположим 8мс. Каждый раз в этом реалтайм цикле (а это тоже таск, не поток), ты берешь все данные из этого "потокобезопасного хранилища" и обрабатываешь их, потом снова уходишь в Task.Delay. |
Ответ: Правильная организация Server<-> client
* async/await, как говорил чувак с какой-то конференции, в WPF (а у меня именно он) после await продолжает выполнение в том же потоке, в котором запущен этот async метод, но это не точно.
* Ну да, async/await - декораторы для генератора кода, а вот реализация (WPF, MVC ) какого-то хрена везде разная, но в WPF работает первый пункт. Наверное связно с тем, что бы не было проблем с UI. * Про остановку потока знаю, но у меня сейчас не таск, а поток отдельный как раз. Если его не тормозить - огромные нагрузки из-за пустого while фактически. |
Ответ: Правильная организация Server<-> client
1. Это правда. Это связано с контекстом синхронизации. Каждое приложение реализует свой особенный контекст. Например, тот который в wpf и winforms, при вызове из ui потока, вернет тебя в ui поток. Это нужно для удобства:
// надо что-то откуда-то загрузить buttonDownload.Enabled = false; var content = await SomeWebClient.GetContent(); buttonDownload.Enabled = true; Вот здесь на последней строке будут проблемы если будешь не в ui потоке (манипуляции с ui контролами можно делать только из ui потока). В ASP NET MVC таких ограничений нет, наоборот чем свободнее будет выбор потока, тем лучше масштабируемость. В веб приложениях вообщем-то пофигу в каком потоке что выполняется, там важны только вещи типа HttpContext.Current 2. Надо проверить что в WPF возвращение к тому же потоку происходит во всех потоках, а не только в UI потоке. 3. Но нафига тебе реальный поток? Создай таск а потоками пуская шедулер занимается (он из тредпула возьмет). Какой такой пустой while? |
Ответ: Правильная организация Server<-> client
![]() Временная реализация выглядит так. Я когда скрин делал, понял самую главную ошибку - цикл сделал бесконечно количество вызовов ожидания подключения - и все ждут, но они никогда не дождутся. Нужно поставить флажок, что если уже поключение ожидается - не ждать нового. UPD. Сменил на таску, благо меняется это одной строчкой. |
Ответ: Правильная организация Server<-> client
Дак в итоге то ты проверил, в WPF если вызвать метод не в UI потоке, то продолжение то где выполнится?
NetProtocol.requestStoping - это твой код? там модификатор volatile есть? |
Ответ: Правильная организация Server<-> client
Цитата:
Цитата:
|
Ответ: Правильная организация Server<-> client
Если это поле используется как минимум в 2-ух потоках (например, в 1 читается, в другом пишется), то лучше сделать его volatile. Если оно к тому же читается многократно, его очень настоятельно рекомендуется сделать volatile.
Дело в том что оптимизирующий компилятор (JIT) может убрать цикл вообще, т.к. видит что там просто доступ к полю (он предположит что значение не меняется в другом потоке). Если отметишь как volatile, ты заставишь компилятор всегда читать из поля данные, то есть запретишь где-либо их кэшировать и т.д. Цитата:
|
Часовой пояс GMT +4, время: 21:51. |
vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot