Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
0 / 0 / 0
Регистрация: 02.07.2016
Сообщений: 15

Баг с ReceiveText (Связка компонентов ServerSocket-ClientSocket)

31.05.2017, 16:05. Показов 1519. Ответов 6

Студворк — интернет-сервис помощи студентам
Пишу клиент-серверное приложение. В серверном варианте присутствует простенький мониторинг подключенных пользователей. Реализовано следующим образом: как только пользователь подключается, то через GetComputerName он отправляет имя компа. Проблема в том, что иногда приходит пустая строка. Причем функция работает нормально, строка записывается и отправляется. Но что-то происходит в процессе передаче, что никак не могу отловить. Может это баг какой-то, а может и нет. Мне просто нужно толковое объяснение тех, кто уже сталкивался с подобным. Можно ли как-то обойти эту проблему. Работе не мешает, конечно, но все равно напрягает.

Ниже код (в комментариях сбита кодировка):
Переменные
C++
1
2
char buffer[MAX_COMPUTERNAME_LENGTH+1];//ћассив символов длиной равной длине названи¤ ѕ*
DWORD size;//ѕеременна¤ размерности в байтах
Процесс отправки

C++
1
2
3
4
5
6
7
void __fastcall TForm1::ClientSocket1Connect(TObject *Sender,
      TCustomWinSocket *Socket)
{
    size=sizeof(buffer);//ќпределение размера массива в байтах
    GetComputerName(buffer,&size);//«апись имени компьютера в массив
    ClientSocket1->Socket->SendText(buffer);
}
Принятие строки сервером
C++
1
2
3
4
5
6
7
8
9
10
void __fastcall TForm1::ServerSocket1ClientConnect(TObject *Sender, TCustomWinSocket *Socket)
{
//При подключении клиента получаем текст с именем компьютера
//В этот же момент срабатывает ClientRead, потому там поставлено условие,
//чтобы лишние данные в таблицу не добавлялись
//Записывает в ListBox в формате: Имя ПК пользователя:номер выделенного сокета в сервере
AnsiString pc = Socket->ReceiveText();
int countCon = ServerSocket1->Socket->ActiveConnections - 1;
ListBox1->Items->Add(pc + ":" + String(ServerSocket1->Socket->Connections[countCon]->SocketHandle));
}
Использовал и доп. переменную AnsiString, чтобы проверить - результат тот же самый
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
31.05.2017, 16:05
Ответы с готовыми решениями:

ServerSocket и ClientSocket
Как передать сообщение не всем а именно нужному клиенту? Например подключено к серверу 4 клиента и как сделать что бы клинты 1 и 3 могли...

ServerSocket and ClientSocket
Подскажите через что проще сделать список подключенных людей к ClientSocket, так чтобы при подключении добавлялась запись и отключении...

ServerSocket и ClientSocket
Дайте пжл инфу или книгу электронную по ServerSocket и ClientSocket... Буду очень благодарен..

6
 Аватар для Dinkin
783 / 556 / 136
Регистрация: 31.05.2013
Сообщений: 3,154
Записей в блоге: 3
31.05.2017, 16:29
Доброго.

При работаете с обычными сокетами необходимо отказываться от передачи строки через сеть...это очень не надежный формат передачи данных с множеством подводных камней.
Переводите свой текст в байты и их отправляйте.

Второе. Просто байты ни когда не шлются. Нужно слать размер байтов, что бы принимающая сторона точно знала какую длину пакета ожидать.

PS. Во время передачи, данные дробятся и порой доходят в несколько этапов. Это может менее заметно если вы тестируете локально. Но как только начнете работать через сеть, все это всплывет.

Добавлено через 2 минуты
В обычных сокетах, луче отказаться от получения строки через ServerSocket1ClientConnec....используйте Read
0
0 / 0 / 0
Регистрация: 02.07.2016
Сообщений: 15
31.05.2017, 16:55  [ТС]
Насчет Read. Здесь идет считывание структуры. Я не придумал как научить сервер отличать структуру от обычного текста. Поэтому сделал через Connect
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
void __fastcall TForm1::ServerSocket1ClientRead(TObject *Sender, TCustomWinSocket *Socket)
 
{
//Принятие зяавки от клиента
Socket->ReceiveBuf(&Mess,sizeof(Mess));
//Если первый символ фамилии не пустой - пришла заявка, иначе не обрабатывать эти данные
if ((Mess.fam[0]))
{
//Блок добавления записи в БД
ADOTable1->Insert();
ADOTable1->Fields->Fields[1]->AsString = String(Mess.pc);
ADOTable1->Fields->Fields[2]->AsString = String(Mess.fam) + ' ' + String(Mess.name[0]) + '.' + String(Mess.otch[0]) + '.';
ADOTable1->Fields->Fields[3]->AsString = String(Mess.otdel);
ADOTable1->Fields->Fields[4]->AsDateTime = Now();
ADOTable1->Fields->Fields[5]->AsString = Mess.problem;
ADOTable1->Fields->Fields[6]->AsString = Mess.podrobno;
ADOTable1->Fields->Fields[7]->AsBoolean = false;
Form1->ADOTable1->Post();
 
//Сортировка записей по дате после добавления
ADOTable1->Sort = "[Время/дата] DESC";
 
//Очистка структуры
strcpy(Mess.pc,"");
strcpy(Mess.fam,"");
strcpy(Mess.name,"");
strcpy(Mess.otch,"");
strcpy(Mess.otdel,"");
strcpy(Mess.problem,"");
strcpy(Mess.podrobno,"");
}
}
0
 Аватар для Dinkin
783 / 556 / 136
Регистрация: 31.05.2013
Сообщений: 3,154
Записей в блоге: 3
31.05.2017, 17:01
Я как то разбирал исходник сокета, давно было , помню что вроде при конекте он не ждет остатки пакета,что не пришли сразу.
Так что луче когда отправляете от клиента пакет, с начало определяйте его назначение.
1
0 / 0 / 0
Регистрация: 02.07.2016
Сообщений: 15
31.05.2017, 17:07  [ТС]
А есть идеи, как определить назначение? У меня есть вариант двойной отправки. Сначала отправляется "системное" сообщение, где определяется назначение, а потом принимается второй поток данных: либо строка, либо структура. Такое может сработать?
0
 Аватар для Dinkin
783 / 556 / 136
Регистрация: 31.05.2013
Сообщений: 3,154
Записей в блоге: 3
31.05.2017, 17:12
Лучший ответ Сообщение было отмечено gogosolo как решение

Решение

Может, только когда Вы споткнетесь на то что вам с начало надо отправлять размер пакета, а потом тип пакета, а потом сам пакет....в общем это надо думать в зависимости от задуманного.

Простой вариант,в структуру добавьте еще один параметр, Тип ПАКЕТА.
1
0 / 0 / 0
Регистрация: 02.07.2016
Сообщений: 15
31.05.2017, 21:02  [ТС]
Попробовал идею с дополнительным параметром в структуре. Естесственно отделил, когда приходит имя компа, когда сообщение. Протестировал запуск сервера 10+ раз (обычно 2-3 раза пустую строку получал), теперь отображается как надо. Спасибо за помощь.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
31.05.2017, 21:02
Помогаю со студенческими работами здесь

ClientSocket и ServerSocket
В общем, задание таково: Клиентская программа оправляет на сервер последовательность из k целых чисел (значения чисел задаются через...

ClientSocket ServerSocket Вопрос
Когда я получил текст (ClientSocket1->Socket->ReceiveText());) то можно его сразу удалить а затем снова принять (вставляю в Timer) ? Типа...

Проблемы с clientsocket и serversocket
Проблемы с их коннектом друг к другу! Ну чтобы нагляднее было возьмем в пример обычный чатик: сервер - подкл. к интернету по средствам...

ServerSocket & ClientSocket
Делал программу на основе Server/ClientSocket, сервер должен был просто отправить клиенту строку текста. Проблема в том, что когда я...

Звук ClientSocket u ServerSocket
Народ, помогите мне пж. Надо передать записать и передать звук с помощью ClientSocket u ServerSocket и так же прочесть его на сервере.Буду...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Вывод данных через динамический список в справочнике
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Функция заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
10 пpимет, которые всегда сбываются
Maks 31.03.2026
1. Чтобы, наконец, пришла маршрутка, надо закурить. Если сигарета последняя, маршрутка придет еще до второй затяжки даже вопреки расписанию. 2. Нaдоели зима и снег? Не надо переезжать. Достаточно. . .
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 31.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru