Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2006.07.30;
Скачать: [xml.tar.bz2];

Вниз

Вопрос про особености протокола 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.016 c
15-1151652157
Артем22
2006-06-30 11:22
2006.07.30
"Компиляторы" e-books


2-1152204491
dest81
2006-07-06 20:48
2006.07.30
Ibquery


15-1151838597
vidiv
2006-07-02 15:09
2006.07.30
Сертификаты


8-1138559567
SKIPtr
2006-01-29 21:32
2006.07.30
Как воспроизвести 2 звуковых файла


2-1152603329
levin_610
2006-07-11 11:35
2006.07.30
registraciia servisov





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский