Форум: "Сети";
Текущий архив: 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