forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   PureBasic (http://forum.boolean.name/forumdisplay.php?f=90)
-   -   Непонятки с TCP/IP (http://forum.boolean.name/showthread.php?t=17047)

jimon 19.07.2012 00:26

Ответ: Непонятки с TCP/IP
 
Цитата:

Сообщение от Dstalk (Сообщение 233277)
Уверен. А вот эта строчка выдает ошибку, но принудительно читает пакет, вместе с возможными кусками последующих пакетов. Этой строчки вообще не будет, если проблема перестанет проявлятся.
А выдает TCPlength.i=PeekL(*TCPBuffer) больше тысячи, потому что в памяти находится первые четыре байта пакета, а там символы, если считать их из памяти как integer, всегда получается больше 1000. Это типа проверка на ошибку пакета...

Да, и по идее, у нормальных пакетов длина всегда меньше 1000.

Забыл сказать - пакеты отправляю прогой на Blitz3D, пробовал двумя способами:
Код:

;1 способ
WriteString streamIP,msg1$
;2 способ
WriteInt streamIP,Len(msg1$)+2
WriteLine streamIP,msg1$

Оба способа дают одинаковые результаты...

а где уверенность что блиц это кладёт в ОДИН TCP ПАКЕТ ? :) TCP пакетный протокол (когда udp - дейтаграммный), и в нём гарантируется прием в точно такой же последовательности как была произведена передача

DStalk 19.07.2012 01:37

Ответ: Непонятки с TCP/IP
 
Пакетный? TCP насколько я помню - непрерывный поток данных, не подразделяющийся на пакеты. Пакетами в данном случае я называю отдельные сообщения в TCP потоке... Как я писал выше оба способа дают одинаковый результат.

moka 19.07.2012 02:07

Ответ: Непонятки с TCP/IP
 
TCP - это поток данных. Протокол может разбивать данные на сегменты, либо наоборот на уровне протокола в системе ждать пока не будет достаточно данных для полного сегмента (Нагглэ Алгоритм).
Тут дело не с протоколом, а с блицем, и не тем как он кладёт всё в кучу или наоборот, а в том что видимо число порой не отправляется последовательно. Блиц старик, и я бы не юзал стандартный функционал для сети (снова).

dimanche13 19.07.2012 10:29

Ответ: Непонятки с TCP/IP
 
доверяй wireshark-у юный падаван
советы его мудры, око его всевидяще
и да прибудет с тобой сила

impersonalis 19.07.2012 10:55

Ответ: Непонятки с TCP/IP
 
Цитата:

Сообщение от MoKa (Сообщение 233287)
Блиц возможно применяет собственный алгоритм склеивания сообщений, тем самым если слишком часто отсылать, может клеить стринги вместе.


Я что-то не очень понял. Разделители типа EOL между строками никуда не денутся. А дейтаграммы и на уровне движка, и на уровне tcp всегда стремятся склеится (лучше отправить 1 раз 500 байт, чем два раза по 250). Функции запроса конкретного типа данных (типа ReadLine) очевидно работают в блокирующем режиме (дожидаясь приёма объекта целиком) с крахом по таймауту, задаваемому функцией TCPTimeouts.

тред не читал @ сразу овтечал

Пётр 19.07.2012 14:20

Ответ: Непонятки с TCP/IP
 
Цитата:

Сообщение от Dstalk (Сообщение 233271)
Вот код:
Код:

ReceiveNetworkData(TCPclientID,*TCPBuffer,4)
TCPlength.i=PeekL(*TCPBuffer)
If TCPlength>1000:TCPlength=1000:PrintN("Packet error!"):EndIf
ReceiveNetworkData(TCPclientID,*TCPBuffer,TCPlength)
TCPPacket=PeekS(*TCPBuffer)

Сколько тестил - он всегда(!) читает сообщение необходимой длины, не больше и не меньше. Но очень редко TCPlength захватывает 4 байта самого сообщения. Просто integer куда-то пропадает...

В этом коде еще нет проверки на то, если сообщение пришло не полностью, но когда на одном компьютере тестишь - это проблем не вызывает, проверял.

Я вообще удивляюсь что работает.
Где гарантия что первый вызов ReceiveNetworkData() запишет в буфер именно 4 байта? А если пришло только, скажем, 2 байта, что тогда?

Где гарантия что второй вызов функции, поместить в буфер именно столько байт, сколько указанно в TCPlength?
Может на момент чтения еще не все данные пришли, вот и будет выше описанный баг.

Если хотите чтобы все работало без сбоев, делайте следующим образом:
Заведите буфер, размером в несколько раз больше чем максимальный размер пакета.
Читайте данные в этот буфер и анализируйте сколько байт реально было прочитано функцией ReceiveNetworkData().
Если меньше положенного, то ждите и через время опять читайте, помещая результат в конец буфера.
Как только приняли все данные, тогда обрабатываете.
Буфер очищаете и опять в него пишите принимаемые данные.

DStalk 19.07.2012 14:52

Ответ: Непонятки с TCP/IP
 
Плин, опять... Как я уже выше писал - еще нет проверки на неполность пакета. Тем не менее, он всегда работает как надо! За последние два месяца это было проверено несколько десятков тысяч раз.

Цитата:

Сообщение от Пётр (Сообщение 233345)
Где гарантия что второй вызов функции, поместить в буфер именно столько байт, сколько указанно в TCPlength? Может на момент чтения еще не все данные пришли, вот и будет выше описанный баг.

Если на момент чтения не все данные пришли, и это я тоже писал выше, он бы считал середину следующего пакета. Такого никогда не происходило. Этот баг проявляется именно в пропаже четырех байт integer`а и очень редко. Скорее всего все-таки блитц виноват.

Прежде чем отвечать, внимательно прочитайте предыдущие сообщения в треде. Спасибо.

Пётр 19.07.2012 16:24

Ответ: Непонятки с TCP/IP
 
Ну смотрите дело ваше.
Я сталкивался с подобным и выше описал как решил проблему.

В таком варианте как сейчас, есть вероятность глюков из-за приема не всех данных пакета.

Пётр 20.07.2012 12:18

Ответ: Непонятки с TCP/IP
 
Кстати, вот один из сценариев пропадания первых 4-ёх байт пакета.

Пакеты отправляются друг за другом и возникает такая ситуация что первые 4 байта нового пакета принимаются с предыдущим пакетом.

Как бороться с этим, описал выше.

DStalk 20.07.2012 12:24

Ответ: Непонятки с TCP/IP
 
это я тоже проверял, пакет принимается ровно столько, сколько нужно - лишнее не захватывает. А вот как 4 байта эти пропадают, тогда уже прога не знает сколько байт считать и получается может захватить последующие пакеты...

Пётр 20.07.2012 14:02

Ответ: Непонятки с TCP/IP
 
Цитата:

Сообщение от Dstalk (Сообщение 233429)
это я тоже проверял

Как проверял?

DStalk 20.07.2012 14:09

Ответ: Непонятки с TCP/IP
 
логи отправленных и принятых данных, сравнивал, анализировал;)

Я уже в этом треде раз 5 написал, что код работает абсолютно нормально. Но очень редко и рандомно пропадают именно 4 байта, других ошибок и багов никогда не было. Пётр, извини конечно, но внимательнее читай тему...

Пётр 20.07.2012 14:29

Ответ: Непонятки с TCP/IP
 
Цитата:

Сообщение от Dstalk (Сообщение 233457)
логи отправленных и принятых данных, сравнивал, анализировал;)

Мне это ни о чем не говорит. Код записи в логи в студию.
Ну или как альтернатива, гадание на кофейной гуще, раз кода нет.

Цитата:

Сообщение от Dstalk (Сообщение 233457)
Пётр, извини конечно, но внимательнее читай тему...

Зачем тогда была создана эта тема если не пытаешься услышать других?
Кому нужно избавится от глюков в проге, мне или тебе?
Я тебе уже несколько раз писал чтобы проверял сколько реально было прочитано байт, но видимо ты невнимательно читаешь.

DStalk 20.07.2012 15:24

Ответ: Непонятки с TCP/IP
 
Код:

PrintN(TCPPacket)
не?)) Практически тоже самое при отправке сообщения.
Ты мне не веришь что других ошибок не возникало, кроме пропажи integer`а. Ну извини, логи у меня выводятся в консоль, и я их не сохраняю.
Предпологалось, что последнее сообщение было на первой странице треда, где я поблагодарил MoKa.
Глюков в программе нет, единственное что нужно проверку на неполность сообщения, но это я и сразу знал, и писал об этом.

Подправил кстати TCPPacket=PeekS(*TCPBuffer,TCPlength) строчку в коде на первой странице, на прием никак не влияет, но в стринг TCPPacket могут записатся куски старых пакетов из буффера, так как он не очищается...

Закрыть бы темку, а то ничего кроме срача тут не предвидится...

Пётр 20.07.2012 15:48

Ответ: Непонятки с TCP/IP
 
Цитата:

Сообщение от Dstalk (Сообщение 233472)
Код:

PrintN(TCPPacket)
не?))

Конечно не! Вот как должно быть.
Код:

RealCountBytes_1 = ReceiveNetworkData(TCPclientID,*TCPBuffer,4)
TCPlength.i=PeekL(*TCPBuffer)
If TCPlength>1000:TCPlength=1000:PrintN("Packet error!"):EndIf

RealCountBytes_2 = ReceiveNetworkData(TCPclientID,*TCPBuffer,TCPlength)
TCPPacket=PeekS(*TCPBuffer)

PrintN(Str(RealCountBytes_1)+"        "+Str(RealCountBytes_2))

Теперь точно покажет сколько байт было принято. И я думаю что при возникновении глюка оно будет не таким как ты предполагаешь.

Цитата:

Сообщение от Dstalk (Сообщение 233472)
Закрыть бы темку, а то ничего кроме срача тут не предвидится...

Раз ты не слушаешь тех, кто уже сталкивался с подобным и старается тебе помочь, то пожалуй да, тему нужно закрыть. Раз тебе помощь не нужна, то зачем вообще создавал тему?

Не выйдет из тебя программиста. Нет логического мышления и не слушаешь тех, кто старается тебе помочь!


Часовой пояс GMT +4, время: 06:59.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot