Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.79/19: Рейтинг темы: голосов - 19, средняя оценка - 4.79
0 / 0 / 0
Регистрация: 28.02.2020
Сообщений: 103

Поток в настоящее время используется предыдущей версией потока

27.10.2024, 00:31. Показов 4772. Ответов 64
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, уважаемые программисты! Писал клиент и сервер. Идея такова, что выбирается listView элемент, затем нажимается кнопка Button1 и сервер отправляет на клиента команду, клиент принимает ее и в ответ шлет сначала эту же команду, затем число строк из своего listView, а затем в цикле пересылаются все строки. Так вот, при первом нажатии срабатывает нормально, результат можно видеть на картинке, а при втором нажатии вылезает ошибка из названия темы. Помогите, кто может, как избавиться от этой ошибки? В архиве прикрепляю проекты Visual Studio клиента и сервера.
Миниатюры
Поток в настоящее время используется предыдущей версией потока  
Вложения
Тип файла: 7z Клиент - Сервер.7z (168.6 Кб, 8 просмотров)
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
27.10.2024, 00:31
Ответы с готовыми решениями:

В некоторых странах Дальнего Востока (Китае, Японии и др.) использовался (и неофициально используется в настоящее время)
В некоторых странах Дальнего Востока (Китае, Японии и др.) использовался (и неофициально используется в настоящее время) календарь,...

В некоторых странах Дальнего Востока (Китае, Японии и др.) использовался (и неофициально используется в настоящее время)
В некоторых странах Дальнего Востока (Китае, Японии и др.) использовался (и неофициально используется в настоящее время) календарь,...

Какие на ваш взгляд ОС Windows являются провальными по сравнению с предыдущей версией и почему?
Всем доброго времени суток уважаемые, пользователи, администрация и гости форума. У меня такой вопрос. Какие на ваш взгляд ОС Windows...

64
0 / 0 / 0
Регистрация: 28.02.2020
Сообщений: 103
05.11.2024, 04:26  [ТС]
Студворк — интернет-сервис помощи студентам
wizard41, Ну вот, визуально повторил ваше приложение. И изучать материал не пришлось. А как оно там работает внутри это уже другой разговор
Вложения
Тип файла: 7z Клиент - Сервер.7z (168.6 Кб, 7 просмотров)
0
0 / 0 / 0
Регистрация: 28.02.2020
Сообщений: 103
05.11.2024, 04:30  [ТС]
P.S. Повторил не только визуально, но и функционально. Но как...
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3453 / 2774 / 575
Регистрация: 04.09.2018
Сообщений: 8,725
Записей в блоге: 3
05.11.2024, 13:10
Цитата Сообщение от Оаг Посмотреть сообщение
И изучать материал не пришлось.
Ну и зря. Посмотрел мельком код Сервера.... Клиент смотреть даже смысла нет. Все ожидаемо плохо.
Даже запустил клиент и сервер - не понятно что и когда нажимать, вылетело два исключения, сервер закрылся по ошибке. Больше экспериментировать не стал.

О явных недоработках и ошибках в коде:
- все опять свалено в кучу, в классе формы.
- метод получения директории exe-файла, это что-то с чем-то:
GetExeDirectory
C#
1
2
3
4
5
6
7
8
private string GetExeDirectory()
{
    string codeBase = Assembly.GetExecutingAssembly().CodeBase;
    UriBuilder uri = new UriBuilder(codeBase);
    string path = Uri.UnescapeDataString(uri.Path);
    path = Path.GetDirectoryName(path);
    return path;
}

- недостижимый код в методах.
- названия кнопок button1, button2... ни о чем не говорят. Играй в угадайку что надо нажать и для чего.
- событие button1_Click что-то отправляет клиенту без всяких проверок: а запущен ли сервер и подключен ли хоть кто-то к нему? На этом, скорее всего, вывалилось приложение у меня, когда я нажал на button1.
- то же, с событием button2_Click, если сервак не запущен, приложение упадет с исключением NullObjectReference.

- класс ServerObject:
- создаются новые клиенты при отправке им сообщений. Те клиенты, что подключились и опознаны сервером AcceptTcpClientAsync(), просто висят в вакууме и никому не нужны.
- нет возможности отменить прослушку - задачи запускаются и улетают в бесконечность, работая сами по себе.
- нет возможности остановить сервер и запустить новый, с другими параметрами (ip, port...).

- класс ClientObject:
- ссылки на ServerObject server, о котором клиенты и знать ничего не обязаны. Клиенты работают с удаленным подключением, получив из него поток; что же из себя представляется сервер и тем более явно ссылаться на него - им ни к чему.
- клиенты получают стримы "просто так", без всяких подключений и проверок что хоть кто-то есть по указанному адресу.
- ничего не Dispose-иться и не удаляется; срем в память чем только можем.
- метод приема почему-то считает, что пришедшие сообщения гарантированно должны начинаться с некоторых символов: нет даже базового представления о протоколе TCP.

... на этом наверное достаточно.
В общем, код похож на невесть от куда выдранные куски, с попытками их хоть как-то связать между собой.
0
0 / 0 / 0
Регистрация: 28.02.2020
Сообщений: 103
05.11.2024, 21:24  [ТС]
wizard41, Простите, я не то скинул, вот то, что хотел скинуть. Два экзешника, копирующие два ваших экзешника
Вложения
Тип файла: 7z Server+Client.7z (12.5 Кб, 9 просмотров)
0
0 / 0 / 0
Регистрация: 28.02.2020
Сообщений: 103
05.11.2024, 21:29  [ТС]
Мы отклонились от темы. Наверно стоит пояснить, что я согласен со всеми, кто написал, что мне нужно изучить тему подробнее. А экзешники я скинул, чтобы показать, что можно скопировать чужое приложение, но что там будет под капотом неизвестно. Так же как вы скинули свои экзешники, чтобы продемонстрировать их работу.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3453 / 2774 / 575
Регистрация: 04.09.2018
Сообщений: 8,725
Записей в блоге: 3
06.11.2024, 01:04
Оаг, Окей.
Какой конечный смысл этой задачи? Сделать, чтобы работало или в учебных целях?
Вот так написал его я, на скорую руку:
wizard41.TcpServerClient.Demo.7z
Изучай..
0
0 / 0 / 0
Регистрация: 28.02.2020
Сообщений: 103
06.11.2024, 19:07  [ТС]
wizard41, Ну, идея заключается в том, что есть несколько клиентов и есть сервер. Они взаимодействуют так: сервер подключается к клиенту, посылает команду, клиент принимает ее, в зависимости от команды, отсылает отчёт (какую-то информацию) и дальше они разрывают соединение. При этом, перед началом работы надо как-то сконфигурировать клиенты, чтобы принимали подключение только от сервера. А сервер должен настроить список клиентов, которым будет отправлять команды. Как-то так.

Добавлено через 38 секунд
Спасибо за пример. Буду изучать
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3453 / 2774 / 575
Регистрация: 04.09.2018
Сообщений: 8,725
Записей в блоге: 3
06.11.2024, 19:12
Оаг, понял. Сервер не должен ни к кому подключаться. Он просто "завелся" и ждет, пока к нему кто-то присосется.
Если увидел клиента, то можно начинать с ним обмен...
В моем примере так и сделано - сервер посылает команду клиенту (getdata), а тот отвечает...
0
0 / 0 / 0
Регистрация: 28.02.2020
Сообщений: 103
06.11.2024, 19:21  [ТС]
wizard41, А если у меня сервер занимается централизованным управлением клиентами, то мне надо, чтобы именно сервер запрашивал подключение у клиентов. Или как по другому? Держать соединения со всеми клиентами всегда открытым? Сервер то может в любое время запросить отчёт у клиента, а как он запросит отчёт, если вы говорите, что клиент должен сначала запросить соединение?
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3453 / 2774 / 575
Регистрация: 04.09.2018
Сообщений: 8,725
Записей в блоге: 3
06.11.2024, 19:28
Оаг, сервер не может ничего запрашивать у клиентов, которых нет. Он работает только с реально подключенными абонентами.
Клиент соединяется с сервером, тот теперь "знает" что есть такой-то клиент... Ну и работает с ним.
0
0 / 0 / 0
Регистрация: 28.02.2020
Сообщений: 103
06.11.2024, 19:34  [ТС]
wizard41, Ну, то есть, если у меня будет 100 клиентов в локальной сети, то мне надо, чтобы соединение с каждым из них было постоянно открыто, чтобы сервер мог в любой момент любому клиенту отправить команду и получить ответ в виде информации?
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3453 / 2774 / 575
Регистрация: 04.09.2018
Сообщений: 8,725
Записей в блоге: 3
06.11.2024, 19:45
Оаг, я думаю, что не надо разрывать соединение с клиентами. Клиент либо жив, либо кот...
Пока клиент есть, с ним сервер работает. Странно делегировать серверу обязанности искать клиентов самому...

Добавлено через 4 минуты
Оаг, это можно в том случае, если сервер заранее "знает" своих клиентов, по ip-адресам, например. Но все равно, зачем ему лишняя нагрузка - отправлять сообщения тому, кого нет. Он должен работать по факту, т.е. с теми, кто к нему подключен в данный момент.

Добавлено через 2 минуты
Само же наличие клиента, который был подключен ранее, определится со следующей посылкой к нему команды. TCP протокол может определить, доставлено сообщение или нет. Если не доставлено, то клиент отвалился...
0
0 / 0 / 0
Регистрация: 28.02.2020
Сообщений: 103
06.11.2024, 20:23  [ТС]
wizard41, Хорошо, тогда другой вопрос. А как мне при получении сообщения сервером, понять, от кого оно пришло? Например, я отправил команду на три клиента, ответ может прийти в разном порядке. Как мне написать код, который определяет, от кого пришло сообщение? Вот до этого у меня был код
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
protected internal async Task ListenAsync()
{
    try
    {
        tcpListener.Start();
        while (true)
        {
            TcpClient tcpClient = await tcpListener.AcceptTcpClientAsync();
            ClientObject clientObject = new ClientObject(tcpClient, this);
            if (!AvailableClients.Contains(clientObject.IP))
                AvailableClients.Add(clientObject.IP);
            clients.Add(clientObject);
            Task.Run(clientObject.ProcessAsync);
        }
    }
    catch (Exception ex)
    {
        Notify.Invoke(ex.Message);
    }
    tcpListener.Stop();
}
 
private async Task ProcessAsync()
{
    while (true)
    {
        try
        {
            string message = await Reader.ReadLineAsync();
            if (message == null) continue;
            Obrabotchik(message);
        }
        catch
        {
            break;
        }
    }
}
Он принимал соединение, а потом запускал задачу отдельно для каждого клиента. И принимал строки в цикле отдельно для каждого клиента с помощью message = await Reader.ReadLineAsync();
То есть у каждого клиента был собственный Reader. Но при большом количестве клиентов это все сильно нагружало процессор.
А как вы предлагаете, мне сначала надо принять подключения от всех клиентов. А потом как-то принимать в коде все сообщения и определять, кому принадлежит сообщение. А до этого не приходилось определять, потому что у каждого клиента был свой Reader и сообщения принимались отдельно для каждого клиента. Так вот как с помощью кода принимать все сообщения и определять, от какого клиента сообщение?

Добавлено через 5 минут
Если что, изначальный код сервера и клиента брался с сайта metanit.com "консольный tcp-чат". Возможно, он просто не подходит под мои задачи
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3453 / 2774 / 575
Регистрация: 04.09.2018
Сообщений: 8,725
Записей в блоге: 3
06.11.2024, 20:34
у каждого клиента есть его EndPoint, который четко определяет кто источник сообщения.
В целом, направление верное: сервер постоянно ждет подключений и принимает их (в отд. потоке). Все подключенные клиенты работают в своих потоках. Сервак рассылает команды тем, кто есть в списке активных клиентов. Если кто-то не получил команду, то выбывает из этого списка...

Добавлено через 1 минуту
можно даже в сам протокол сообщений вкладывать "имя" клиента... Тут вариантов тьма, на что фантазии хватит..
0
0 / 0 / 0
Регистрация: 28.02.2020
Сообщений: 103
06.11.2024, 20:58  [ТС]
wizard41, Окей, спасибо за советы. Буду изучать и пытаться что-то сделать
0
2290 / 1606 / 400
Регистрация: 26.06.2017
Сообщений: 4,772
Записей в блоге: 1
06.11.2024, 23:56
Заранее извиняюсь если сказанное не будет иметь отношения к задаче ТСа.
wizard41, не стоит упрямо выворачивать любую задачу под стандартные решения. Это я про то, что сервер всегда тупо слушает. Возможны крайне редкие нестандартные решения, которые имеют место быть.
Рассмотрим такой пример: есть сервер, который обязан собирать инфу с распределённых объектов, пусть это будут эл.подстанции (далее ЭП). Когда какая-то ЭП подключается в систему, то она обязана зарегистрироваться на сервере, т.е. предоставить все свои данные и IP-адрес тоже, правда он должен быть статическим. В случае изменения контактной информации её актуализация на сервере также ложится на клиента (ЭП). На протяжении любого промежутка времени ЭП молчат, но собирают или не собирают какие-то данные. Внезапно, очнувшемуся в 3 часа 47 минут ото сна, диспетчеру вздумалось узнать какой-то показатель с ЭП №ХЗ, он жмёть кнопочку и... Что называется продолжите фразу. Всё просто, именно сервер будет стучаться в сторону ЭП и запрашивать у неё данные. Стандартный подход тут не эффективен, так как в этом случае ЭП (клиенты) должны периодически стучаться на сервер, сообщать ему "я жив" и всё в этом духе. Но зачем?
Пример конечно оторван от действительности потому, что в реалиях мониторящиеся объекты почти всегда на связи и именно они натравливаются на сервер, а не наоборот. Но что если нам такое не нужно, а нужно как написано выше.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3453 / 2774 / 575
Регистрация: 04.09.2018
Сообщений: 8,725
Записей в блоге: 3
07.11.2024, 00:44
Uswer, не спорю. Описанное тобой - это стандартная реализация Мастер-подчиненный, где мастер задает тон.
Но я про этот вариант и сам сказал ранее.
Если у ТСа сервер знает всех своих клиентов, то можно сделать и так. Но нужно иметь в виду, что будет затрата времени на выяснение - кто на связи..
0
0 / 0 / 0
Регистрация: 28.02.2020
Сообщений: 103
07.11.2024, 02:04  [ТС]
wizard41, так если это настраивать в локальной сети, то можно сконфигурировать сервер, чтобы имел список ip-адресов, к которым надо обращаться. И не думаю, что затрата времени для одного клиента будет такой уж большой, если нам не нужно получать ответ моментально. А вот если отослать команду сразу всем клиентам, то сначала придется действительно устанавливать со всеми ними соединение.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3453 / 2774 / 575
Регистрация: 04.09.2018
Сообщений: 8,725
Записей в блоге: 3
07.11.2024, 13:26
Оаг, ну.. не знаю, по мне так вариант где сервер всех знает и опрашивает - в данном случае просто лишний. У него будет лишняя работа.
Сервер и так узнает клиента(ов), когда они подключатся. А когда кто-то не подключен, то он не подключен, и смысл его опрашивать какой?

Допустим пример с зарплатой на карту: можно в день зарплаты каждые 5 минут заходить в онлайн-банк и проверять, пришли ли деньги. Но это лишняя работа: когда деньги поступят на счет - мы и так узнаем (придет SMS, Push...). Так и здесь.

Но выбор за тобой, делай как нравится..
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
08.11.2024, 11:32
Цитата Сообщение от Оаг Посмотреть сообщение
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
while (true)
    {
        try
        {
            string message = await Reader.ReadLineAsync();
            if (message == null) continue;
            Obrabotchik(message);
        }
        catch
        {
            break;
        }
    }

Тут лютая ошибка: при закрытии соединения ReadLine возращает null и получаете вечный цикл, который отлично забьет вам ядро CPU под 100%. Несколько переподключений, и лежать будет весь сервер.

Вообще возьмите за правило что while(true) аналогично goto: лучше избегать по возможности.

Цитата Сообщение от Оаг Посмотреть сообщение
Если что, изначальный код сервера и клиента брался с сайта metanit.com "консольный tcp-чат". Возможно, он просто не подходит под мои задачи
Там очень куцый пример, прям самый минимум. В идеале у вас должен быть класс Session (или его аналог, у вас я так понимаю это ClientObject), который инкапсулирует текущее подключение клиента и основную работу с его соединением. Слушатель-сервер ожидает подключение, далее полученый сокет/клиент отдается фабрике, она возвращает сессию, и она закидывается в общую потокобезопасную(!) коллекцию.

А дальше уже можно по разному реализовывать взаимодействие с клиентами: через агрегатор, команды, ивенты или ту же MQ. Я обычно практикую подход через Handlers:
- на каждый тип сообщения создается обработчик
- набор таких обработчиков агрегируется и передается сессии
- входящее сообщение скармливается агрегатору, он ищет нужный обработчик и вызывает его

Если нужно просто кому-то, что-то отравить без ожидания входящего сообщения, то тут вообще элементарно: фоновый сервис просто должен иметь доступ к списку сессий.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.11.2024, 11:32

Описать два потока: первый поток записывает данные в буферную память, а второй поток – считывает
Как написать на языке С программу, которая содержит две функции, описывающие два потока? Первый поток записывает некоторые данные в...

Нужны ли эти теги в настоящее время
Обращают ли поисковики внимание на теги: <meta name="keywords" content="" /> <meta name="description" content="" /> ...

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

Вчера составила $ 15,12, в настоящее время составляет $ 14,82?
адмоб, счёт, вчера составила $ 15,12, в настоящее время составляет $ 14,82 ? почему в минус ???

Немецкий язык. Перфект и настоящее время?
ВОПРОС Изучая перфект, я прочитал следующее примечание. Привожу его дословно. Важно! Перфект в немецком языке в отличие от...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru