Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник
Коллекция курьезных вопросов из форумов
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »

Чат на дельфи


Никифиров И.П.   (12.07.19 18:25

Привет мастера! Сделал для себя и друзей чат на D2010, использовал IdUDPServer и IdUDPClient из стандартных компонент. В локалке все работало без проблем, решил попробовать по удаленке. На один комп прикрутил внешний IP, теперь те ПК что с ним в локалке общаются как и раньше,а вот один ПК что далеко и хотле приконнектить в наш чат по внешнему адресу не видит ни своих, ни наших сообщений,хотя мы его сообщения видим в нашем чате. В чем может быть проблема?


Никифиров И.П.   (12.07.19 18:30[1]

коннект так сделан:
IdUDPClient1.Active:=False;
IdUDPServer1.Active:=False;
IdUDPClient1.Host:='внешний адрес';
IdUDPClient1.Active:=True;
IdUDPServer1.Active:=True;

отсылка сообщений:
IdUDPClient1.BufferSize:=Length(Edit1.Text);
IdUDPClient1.SendBuffer(BytesOf(Edit1.Text));

прием сообщений:
procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
 AData: TBytes; ABinding: TIdSocketHandle);
begin
Memo1.Lines.Add(StringOf(AData));
end;


Никифиров И.П.   (12.07.19 18:48[2]

Внешний адрес на одном из ПК что в локалке были


KSergey ©   (15.07.19 09:54[3]

Проблема в коде вычитывалки.
(далее общие рассуждения, конкретно сказать в чем именно проблема - не берусь)

1) Возможно к удалённому хосту UDP вообще не приезжает.
Тут я не очень силён что надо сделать и как проверить. Может есть нюанс вообще в размере пакета UDP?

2) Код вычитывания - точно неправильный.
При сетевом взаимодействии есть неочевидная фигня про то, что если вы отправляете какое-то количество байтов за одну операцию, то на приёмном конце это приезжает вовсе не единым куском! Отправленная последовательность байтов может приезжать совершенно произвольными фрагментами: по 1 байту, по 2, по 13, по 139 и т.д. в любых произвольных комбинациях. Еще раз подчернку: это происходит даже если отправляете вы всё единым куском!
Соответственно, на приёмном конце надо эти последовательности байтов собрать и по какому-то маркеру понять, вот он, конец очередного сообщения.
Более того, если вы сделали два раза подряд .Send(что-то там), то на приёмный конец всё это может приехать так, что (например):
  - половина первого сообщения
  - остаток первого сообщения (первого вызова Send) и 17 байтов следующего
  - остаток второго сообщения
И все вот эти истории ваш протокол обмена должен уметь распознавать.
Более того, т.к. UDP  - то в общем случае надо еще уметь распознавать как потери (это протокол не гарантированной доставки), так и приезд кусков в произвольно порядке! (если я только не ошибаюсь, возможно про произвольный порядок я вру, не помню уже деталей)
Выход - перейти на TCP, там хотя бы с гарантированностью доставки будет решено за вас.

В локалке вы всех этих приколов просто не замечаете, т.к. там обычно все бегает большими пакетами, которые не фрагментируются. (если говорить про отправку небольших сообщений, до 512 байтов грубо говоря)
А вот в реальном интернете при прохождении кучи роутеров и разных сред передачи сигнала с разными физ. характеристиками каждый роутер передаёт как ему вздумается, и разбивает как сумеет передать через свою физическую среду передачи.

Итого:
   Memo1.Lines.Add(StringOf(AData));
не факт, что тут соберётся корректно строка, особенно учитывая, что в D10 применяется UNICODE кодировка, т.е. по 2 байта на символ.
Если в пакете приедет не четное количество байт - корректно собрать из них строку ен удастся.
Таким образом, сначала требуется как-то убедиться, что приехала целиком вся строка,  и только после этого делать из неё StringOf()
Если приехала не целиком строка - то надо приехавшую часть сохранить, когда доедет следующий кусок - пристыковать к предыдущему и снова проверить где там конец строки. (напомню, что может приехать и два сообщения разом, частично, так что искать конец строки надо и в середине, тогда оставшийся хвост - следующее сообщение (или его начало)

Маркером конца строки можно например считать два подряд нулевых символа, только к Length(Edit1.Text) их надо тогда добавить и не забыть послать при отправке BytesOf()


Никифиров И.П.   (15.07.19 11:01[4]

>KSergey Есть примерчик какой на ТСР? может из личных архивов?


KSergey ©   (15.07.19 14:17[5]

Нету. На дельфи не делал.
Но вроде там же ровно тоже самое должно быть, только компоненты со словом TCP внутри, вместо UDP


Никифиров И.П.   (15.07.19 15:26[6]

>KSergey Буду искать тогда... Спасибо!


brother ©   (14.08.19 14:16[7]

udp запрещены в инете....


Styx ©   (14.08.19 21:35[8]


> udp запрещены в инете....

Опять Роскомнадзор???


версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо