Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.07.30;
Скачать: CL | DM;

Вниз

Вопрос про особености протокола TCP   Найти похожие ветки 

 
tcpz   (2006-01-08 17:44) [0]

Скажите пожайлуста, если я отправляю скажем

test1 test2 test3

возможна ситуация когда данные придут не так как планировалось, а конкретно test2 test1 test3

Если да, как этого избежать?

Спасибо!


 
Piter ©   (2006-01-08 17:54) [1]

tcpz   (08.01.06 17:44)
а конкретно test2 test1 test3


Нет, такое невозможно.


 
tcpz   (2006-01-08 18:10) [2]

Спасибо я так и думал.


 
Цукор5   (2006-01-08 18:44) [3]

2 tcpz
Такое возможно в UDP.


 
Kacnep ©   (2006-03-13 09:17) [4]

Инди 10 Дельфи 6
А именно в УДП как избежать этого?
Сервер переколбашивать никак не получится... :((
Во мой код приема...

         SendComm(FPreComm+"status"); //отправляем запрос на сервер
         if Terminated then break;

{!!! Пытаемся собрать из кучи пришедших УДП пакетов один нормальный !!!}
         s:="";
         repeat
           tmps:=i_uc.ReceiveString;
           if tmps<>"" then s:=s+tmps;
         until tmps="";
         if Terminated then break;

         f_Main.AddLog("***** CS ***** : Answer: "+s,LogF);


Будет ли S содержать ВСЕ отправленные пакеты? и в верном порядке? если нет тоо что можете посоветовать?


 
Сергей М. ©   (2006-03-13 09:56) [5]


> Будет ли S содержать ВСЕ отправленные пакеты?


Не обязательно.


> в верном порядке?


Тоже не обязательно.


> тоо что можете посоветовать?


Включать в состав отправляемого инф.сообщения нечто вроде его "порядкового номера" или метки времени отправки.

На принимающей стороне при получении очередной дейтаграммы анализировать эту инф-цию и в соответствии с этим размещать полученные данные в нужную позицию потока принимаемых дейтаграмм.


 
Каспер   (2006-03-13 10:25) [6]

Спасибо!
хех :((
Сервак НИКАК нельзя изменить :(
Буду пытаться рыть.
Вот что интересно ...
я с помощью инди получаю строки
а если попробовать получить буфер ?
Будут ли идентичны рез-ты? Я думаю может какая то инфа теряеться при получении строк - скажем пара хитрых первых байт в которых зашифрована длина пакета и его номер?

В соответствии с этим вопрос.
В 10ке инди
var
 tb:TBytes;
вызывает
[Error] u_CS.pas(74): Undeclared identifier: "TBytes"
а для приема буфера требуется
сколько реально получил данных:=i_uc.ReceiveBuffer(var ABuffer :TBytes ;таймаут)

Что за новый тип такой? и можно эту строку написать правильно?
Спасибо.


 
Сергей М. ©   (2006-03-13 10:45) [7]


> думаю может какая то инфа теряеться при получении строк
> - скажем пара хитрых первых байт в которых зашифрована длина
> пакета и его номер?


Тебе протокол прикладного инф.обмена с сервером вообще известен ?


> Будут ли идентичны рез-ты?


Вот фрагмент исходника, делай выводы сам:


function TIdUDPBase.ReceiveString(var VPeerIP: string; var VPeerPort: integer;
const AMSec: Integer = IdTimeoutDefault): string;
var
 i: integer;
begin
 SetLength(Result, BufferSize);
 i := ReceiveBuffer(Result[1], Length(Result), VPeerIP, VPeerPort, AMSec);
 SetLength(Result, i);
end;

function TIdUDPBase.ReceiveString(const AMSec: Integer): string;
var
 VoidIP: string;
 VoidPort: Integer;
begin
 result := ReceiveString(VoidIP, VoidPort, AMSec);
end;



> Что за новый тип такой?


Выполни поиск "TBytes" по исх.текстам Indy


 
Kacnep ©   (2006-03-13 10:51) [8]

Все как всегда разрыл в исходниках :)
Насчет NBytes вопрос снят.


 
Kacnep ©   (2006-03-13 13:24) [9]

Своими силами потерпел полное поражение :(

 function Communicate($command)
 {
   //If there is no open connection return false
   if(!$this->connected)
     return $this->connected;

   //write command on socket
   if($command != "")
     fputs($this->socket, $command, strlen($command));

   //get results from server
   $buffer = fread ($this->socket, 1);
   $status = socket_get_status($this->socket);
   $buffer .= fread($this->socket, $status["unread_bytes"]);

   //If there is another package waiting
   if(substr($buffer, 0, 4) == "\xfe\xff\xff\xff")
   {
     //get results from server
     $buffer2 = fread ($this->socket, 1);
     $status = socket_get_status($this->socket);
     $buffer2 .= fread($this->socket, $status["unread_bytes"]);

     //If the second one came first
     if(strlen($buffer) > strlen($buffer2))
       $buffer = substr($buffer, 14) . substr($buffer2, 9);
     else
       $buffer = substr($buffer2, 14) . substr($buffer, 9);

   }

   //In case there is only one package
   else
     $buffer = substr($buffer, 5);

   //return unformatted result
   return $buffer;

 } //function Communicate($buffer)


Это код отправки на сервер некой команды, потом получение и разбор УДП пакетов. Это ПХП.
В общем я не смог :( может кто поможет...? Разбор и получение УДП сделать?
:(((


 
Сергей М. ©   (2006-03-13 14:01) [10]


> Kacnep ©   (13.03.06 13:24) [9]


Тебе был задан конкретный вопрос, известен ли тебе прикладной протокол ..

Соблаговоли ответить на него ..


 
Eraser ©   (2006-03-13 14:38) [11]


> Kacnep ©   (13.03.06 13:24) [9]


> Это ПХП.

http через UDP... оригинальное решение однако )


 
Каспер   (2006-03-13 20:37) [12]

2 Cергей
Попытаюсь как смогу ответить...
Напрямую - ответ НЕТ. Нашел в инете некий модуль и методом анализа, проб и ошибок приспособил его для своих нужд. Разобраться до конца с кодом на ПХП не получилось. :(

2 Эрейзер
Не я придумал. Для  людей кто писал сей модуль - было удобнее проще или не знаю как и почему использовать ПХП. Мне это не подходит.

2 Олл
Требуется перевести  с максимальнотвозможной точностью этот ПХП код на Дельфи под Инди 10.
Пакет приходит иногда не один :(
Сам не смог. прошу помощи...


 
Каспер   (2006-03-13 20:39) [13]

2 Сергей
Другими словами эта процедура  -все что я имею. И знаю что она работает. :(


 
Eraser ©   (2006-03-13 22:11) [14]


> Каспер   (13.03.06 20:37) [12]

уверен что эта процедура отправляет данные по UDP?


 
Kacnep ©   (2006-03-14 06:28) [15]

2 Эрейзер
Уверен!
Вот от чего я отталкивался! Не хотел захламлять но видимо придеться  -потом надеюсь модер не обидиться и потрет.
Вот от чего я начал писать этот проект.
НО ПОВТОРЮСЬ! Нужно правильно перевести на Дельфи в Инди кусочек кода приведеный выше. Там как раз идет разбор УДПшных пакетов. Это единственная инфа по протоколу используемому утилитой rcon которой я владею. УВЕРЕН ее достаточно!

<?php

// ************************************************************************
//PHPrcon - PHP script collection to remotely administrate and configure Halflife and HalflifeMod Servers through a webinterface
//Copyright (C) 2002  Henrik Beige
//
//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU Lesser General Public
//License as published by the Free Software Foundation; either
//version 2.1 of the License, or (at your option) any later version.
//
//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public
//License along with this library; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// ************************************************************************

class Rcon
{

 var $challenge_number;
 var $connected;
 var $server_ip;
 var $server_password;
 var $server_port;
 var $socket;

 //Constructor
 function Rcon()
 {
   $this->challenge_number = 0;
   $this->connected = true;
   $this->server_password = "";
   $this->server_password = 27015;
   $this->server_password = "";
 }

  //Open socket to gameserver
 function Connect($server_ip, $server_port, $server_password = "")
 {
   //store server data
   $this->server_ip = gethostbyname($server_ip);
   $this->server_port = $server_port;
   $this->server_password = $server_password;

   //open connection to gameserver
   $fp = fsockopen("udp://" . $this->server_ip, $this->server_port, &$errno, &$errstr, 5);
   if($fp)
     $this->connected = true;
   else
   {
     $this->connected = false;
     return false;
   }

   //store socket
   $this->socket = $fp;

   //return success
   return true;

 } //function Connect($server_ip, $server_port, $server_password = "")

 //Close socket to gameserver
 function Disconnect()
 {
   //close socket
   fclose($this->socket);
   $connected = false;

 } //function Disconnect()

 //Is there an open connection
 function IsConnected()
 {
   return $this->connected;
 } //function IsConnected()

 //Get detailed player info via rcon
 function ServerInfo()
 {
   //If there is no open connection return false
   if(!$this->connected)
     return $this->connected;

   //get server information
   $status = $this->RconCommand("status");

   //If there is no open connection return false
   //If there is bad rcon password return "Bad rcon_password."
   if(!$status || trim($status) == "Bad rcon_password.")
     return $status;

  //format global server info
   $line = explode("\n", $status);
   $map = substr($line[3], strpos($line[3], ":") + 1);
   $players = trim(substr($line[4], strpos($line[4], ":") + 1));
   $active = explode(" ", $players);

   $result["ip"] = trim(substr($line[2], strpos($line[2], ":") + 1));
   $result["name"] = trim(substr($line[0], strpos($line[0], ":") + 1));
   $result["map"] = trim(substr($map, 0, strpos($map, "at:")));
   $result["mod"] = "Counterstrike " . trim(substr($line[1], strpos($line[1], ":") + 1));
   $result["game"] = "Halflife";
   $result["activeplayers"] = $active[0];
   $result["maxplayers"] = substr($active[2], 1);

   //format player info
   for($i = 1; $i <= $result["activeplayers"]; $i++)
   {
     //get possible player line
     $tmp = $line[$i + 6];

     //break if no more players are left
     if(substr_count($tmp, "#") <= 0)
       break;

     //name
     $begin = strpos($tmp, "\"") + 1;
     $end = strrpos($tmp, "\"");
     $result[$i]["name"] = substr($tmp, $begin, $end - $begin);
     $tmp = trim(substr($tmp, $end + 1));

     //ID
     $end = strpos($tmp, " ");
     $result[$i]["id"] = substr($tmp, 0, $end);
     $tmp = trim(substr($tmp, $end));

     //WonID
     $end = strpos($tmp, " ");
     $result[$i]["wonid"] = substr($tmp, 0, $end);
     $tmp = trim(substr($tmp, $end));

     //Frag
     $end = strpos($tmp, " ");
     $result[$i]["frag"] = substr($tmp, 0, $end);
     $tmp = trim(substr($tmp, $end));

     //Time
     $end = strpos($tmp, " ");
     $result[$i]["time"] = substr($tmp, 0, $end);
     $tmp = trim(substr($tmp, $end));

     //Ping
     $end = strpos($tmp, " ");
     $result[$i]["ping"] = substr($tmp, 0, $end);
     $tmp = trim(substr($tmp, $end));

     //Loss
     $tmp = trim(substr($tmp, $end));

     //Adress
     $result[$i]["adress"] = $tmp;

   } //for($i = 1; $i < $result["activeplayers"]; $i++)

   //return formatted result
   return $result;

 } //function ServerInfo()

?>


 
Плохиш ©   (2006-03-14 11:29) [16]

А что здесь правила уже изменились? или мы на форуме по пхп находимся?


 
Kacnep ©   (2006-03-14 13:27) [17]

2 Плохиш
я вытавил код протокола в другом языке писаный.
Требуется решить проблему с фрагментированными УДП пакетами в Дельфи с использованием инди 10, по аналогии с поцедурой которая описана выше этого длинного поста на ПХП.


 
Сергей М. ©   (2006-03-14 13:33) [18]


> Kacnep ©   (14.03.06 13:27) [17]


Многое (если не все) зависит от реализации ПХПшного fread() в случае когда он работает с UDP-гнездом .. Ибо как таковое чтение из UDP-гнезда сводится в вызову ф-ции Winsock.recvfrom(), особенности логики работы которой ты в состоянии прочитать/осмыслить самостоятельно.


 
Kacnep ©   (2006-03-14 14:02) [19]

2 Сергей
В таком случае если не рыть глубже это мертвое начинание... :(
Тогда возьмем тупо предположим что весь разбор пришедших пакетов лежит тут
//get results from server
  $buffer = fread ($this->socket, 1);
  $status = socket_get_status($this->socket);
  $buffer .= fread($this->socket, $status["unread_bytes"]);

  //If there is another package waiting
  if(substr($buffer, 0, 4) == "\xfe\xff\xff\xff")
  {
    //get results from server
    $buffer2 = fread ($this->socket, 1);
    $status = socket_get_status($this->socket);
    $buffer2 .= fread($this->socket, $status["unread_bytes"]);

    //If the second one came first
    if(strlen($buffer) > strlen($buffer2))
      $buffer = substr($buffer, 14) . substr($buffer2, 9);
    else
      $buffer = substr($buffer2, 14) . substr($buffer, 9);

  }

  //In case there is only one package
  else
    $buffer = substr($buffer, 5);

  //return unformatted result
  return $buffer;


и что мы знаем что пришли 1..2 пакета у которых в заголовке 4 байта если первый пакет то #255#255#255#255 если второй то #254#255#255#255.
Это то что я понял...
А дальше они как то волшебным образом их компонуют в один если их два :(
Как на дельфи проверить после прихода одного пакета -есть ли еще что нить? В общем самое классное если кто то знаком с ПХП хотяб на минимальном уровне :( Тогда легко переведется


 
Сергей М. ©   (2006-03-14 14:06) [20]

С чего ты вообще взял, что некая инф-ция отправлена сим сервером в виде нескольких пакетов ?


 
Каспер   (2006-03-14 19:19) [21]

2 Сергей
Клиент написаный на ПХП полностью рабочий!
Он реально работает!
Я думал смогу расковыряв то что мне нужно в его коде написать маааленькую приблуду :( не получилось - не смог разобраться.
Поэтому вылез на форум, расширил проблему (фрагментация Н пакетов - и их сбор) поискал - нашел наиболее подходящий топик. И продолжил его. Я не сказал бы что ничего не понимаю в сетевом программировании. И Уважаемого Подгорецкого перевод прочел. До этого писали свою аську -как раз на ней учились. Т.е. саму проблему фрагментирования УДП пакетов знаю и представляю - но с инди не получается = чего то недопонимаю. Вот и прошу помощи. Требуеться разобрать пришедшие один или два пакета - пример разбора приведен но на ПХП а нужно в Инди :(
Мастера! Помогите! Плиз.


 
OldNaum ©   (2006-03-14 19:48) [22]

каспер. иди на sourceforge.net и фильтруй по Counter-Strike. да прибудет с тобой сила, а со мной мои телепатические способности )


 
Сергей М. ©   (2006-03-15 09:56) [23]


> саму проблему фрагментирования УДП пакетов знаю и представляю


Фрагментирование относится не к UDP, а к низлежащему IP,

http://www.zeiss.net.ru/docs/technol/tcpip/tcp11.htm#t115000


 
VirEx ©   (2006-03-19 20:35) [24]

дайте как вспомню, стек протокола айй пи:
программный
транспортный
туннельный
аппаратный

UDP находится в транспортном, вроде... ик, ик :)


 
Kacnep ©   (2006-03-20 13:07) [25]

2 ОЛЛ
Люди... облазил кучу сайтов с примерами -НО ОНИ ВСЕ либо на СИ либо на РНР :( А там типа все просто - можно получить размер посылки. А потом уже исходя из нее получать и дефрагментировать пакеты.
Тогда вопрос немного сдвину в другую плоскость
Если сервер передал мне ХYZ байт - что я пока не знаю.
Пришла какая то часть (первый пакет) - МОГУ ли я как нить узнать размер всей посылки из первого пакета? Если в теле не шифруется (не отправляется специально) размер всей посылки.
Что то типа TidUDPClient.РазмерВсейПосылки_ЧьейЧастьюЯвляетсяЭтотКусок?


 
Polevi ©   (2006-03-20 13:39) [26]

нет


 
VirEx ©   (2006-03-20 22:23) [27]

да


 
Piter ©   (2006-03-20 22:28) [28]

не знаю


 
VirEx ©   (2006-03-20 22:31) [29]

а кто воздержится?


 
Kacnep ©   (2006-03-21 05:10) [30]

Главное во всех примерах на тех же СИях возможно собрать пакеты воедино а в дельфях получаеться нет? - не поверю!


 
Polevi ©   (2006-03-21 09:07) [31]

>Kacnep ©   (21.03.06 05:10) [30]
делфи вообще ацтой
VirEx знает как, спроси у него


 
Сергей М. ©   (2006-03-21 09:12) [32]


> Kacnep ©   (21.03.06 05:10) [30]


Поясни, что ты подразумеваешь под "пакетами" ..

На уровне UDP есть сообщения (ну или дейтаграммы), а пакеты - это на уровне IP .. Разбитие сообщения на пакеты и сборка его из пакетов - не твоя забота .. Твоя забота - прочитать принятое сообщение либо целиком либо последовательно, фрагмент за фрагментом ..


 
Kacnep ©   (2006-03-22 08:52) [33]

Всем Спасибо!
Отдельное спасибо Сергею за попытку по настоящему понять проблему тупня. :(((
Проблема решена и совсем не втом месте. Дельфи и Инди рулят! Просто мозг нужно заряжать не орехами и главное вовремя :))).
В общем приходило нормально оба пакета! Прога ИХ НОРМАЛЬНО СУММИРОВАЛА. Но! Смотрим как

string:=1пакет;
если есть второй пакет то string:=string+второй пакет

И ВНИМАТЕЛЬНО ВИДЯ :))) что первый пакет оканчивается на #0#0!!!! (и это все в тип string :( ну е ма е %( ) что же получиться если к строке завершенной 0 добвить строку... :(

В общем ИНДИ Железно работаю!
Еще раз спасибо всем... Иногда трассировка помогает :)



Страницы: 1 вся ветка

Текущий архив: 2006.07.30;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.028 c
2-1152634378
AlonZo
2006-07-11 20:12
2006.07.30
Занесение системной даты в Edit


15-1151417957
ArtemESC
2006-06-27 18:19
2006.07.30
Как узнать где SoundBlaster: порт, DMA-канал ...


15-1151791564
TUser
2006-07-02 02:06
2006.07.30
Никто не поможет прогнать файл через ТеХ?


2-1152213937
malyar
2006-07-06 23:25
2006.07.30
какой прогой следить за DLL


1-1149076648
blackcrazzy
2006-05-31 15:57
2006.07.30
Edit и ComboBox в DBGrid