Форум: "Сети";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];
ВнизНадёжный способ приёма Найти похожие ветки
← →
delpher_gray (2003-09-17 11:16) [0]Вот заготовка программы:
program PServer;
uses
SysUtils, ScktComp, Windows;
type
TServer = class
private
procedure ClientConnectEvent(Sender: TObject; Socket: TCustomWinSocket);
procedure ClientReadEvent(Sender: TObject; Socket: TCustomWinSocket);
end;
var
hMutex: THandle;
ServerClass: TServer;
ServerSocket1: TServerSocket;
Msg: TMSG;
Cancel: boolean;
procedure TServer.ClientConnectEvent(Sender: TObject; Socket: TCustomWinSocket);
begin
// CODE
end;
procedure TServer.ClientReadEvent(Sender: TObject; Socket: TCustomWinSocket);
begin
// CODE
end;
begin
hMutex := CreateMutex(nil, false, "Server");
if WaitForSingleObject(hMutex, 0) <> wait_TimeOut then
begin
ServerSocket1 := TServerSocket.Create(nil);
ServerSocket1.ServerType := stNonBlocking;
ServerSocket1.Port := 1379;
try
ServerSocket1.Open;
except
Cancel := true;
end;
while not Cancel do
begin
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
Sleep(5);
end;
ServerSocket1.Close;
ServerSocket1.Free;
end;
end.
Подскажите как я могу принимать от клиента команды надёжным путём ? Команды могут быть разные...
например команда выключения монитора, или список файлов на диске...
← →
Digitman (2003-09-17 11:22) [1]а какие вообще сомнения в надежности ?
в связи с чем такой вопрос возник ?
← →
Verg (2003-09-17 15:03) [2]
> TServer.
К чему описание этого класса?
Каким боком TServer участвует в программе?
← →
zippo (2003-09-17 19:13) [3]&&&&
← →
Slym (2003-09-18 05:10) [4]Все упирается в протокол обмена сообщениями!
Сделай типа разделы команд:
FILE
SHELL
CMD
и пр.
а далее подразделы типа:
FILE LOAD
FILE UPLOAD
FILE LIST
FILE DIR
для файл можно использовать например команды ftp протокола...
SHELL EXECUTE
А после команды параметры например с "комма делиметром":
FILE UPLOAD file="c:\autoexec.bat";size=1024
Команду завершай например #13#10 (перевод строки) или #0 (как в пичар)
А далее (для команды FILE UPLOAD file...) сам файл все 1024 байта
FILE LIST directory="c:\";mask="*.*";atrib="FDARSH";style="NSAD"
atrib:File,Dir,Archive,Readonly,Sys,Hiddden
style:Name,Size,Attrib,Date
Отват на команду список файлов с разделителем #13#10 или #0
Если что-то не понятно... бросай это дело
← →
delpher_gray (2003-09-18 14:22) [5]2Verg:
TServer - это класс самого сервера ! Программа консольного типа...
2Slym:
Пасиба за подсказку !
Но в этом есть такое западло...
Например я послал команду с клиенда этуму серверу типа:
FILE LOAD file="c:\file.zip"#0
Сервер сразу же мне перешлёт файл, а как мне отделить этот файл от других команд ? Как узнать что это именно файл ??
← →
Карелин Артем (2003-09-18 14:41) [6]Сигнатуру заведи или передавай файлы в отдельном коннекте.
← →
Verg (2003-09-18 16:44) [7]
> TServer - это класс самого сервера ! Программа консольного
> типа...
Я все понимаю.
Но кто (что) обрабатывает события у ServerSocket1?
Где назначения обработчиков?
Где, в конце концов, ServerClass:=TServer.Create?
← →
delpher_gray (2003-09-18 16:59) [8]2Verg:
Правильно ! Забыл написать :))
----------
Плиз подскажите как разделять команды, если использовать пример протокола Slym"а ?
← →
Digitman (2003-09-18 17:31) [9]
> delpher_gray
с протоколом Slym"a тебе придется лексер/парсер реализовывать
дурацкая, думаю, доп.работа ради десятка "языковых" конструкций
кодируй разделы и команды в разделах неким числовым идентификатором строго опред.типа, например, Word
тогда при приеме кодов разделов и команд ты будешь ожидать строго определенное число байт (при Word - 2 байта)
пусть
FILE = 1
CMD = 2
SHELL = 3
пусть
LOAD = 1
UPLOAD = 2
DIR = 3
LIST = 4
тогда на принимающей стороне
case Section of
1: ... речь идет о файловых операциях
2: ... спец.команды
3: ... обращение к оболочке
end;
и т.д. и т.п.
← →
delpher_gray (2003-09-18 20:04) [10]2Digitman:
Насколько я понял, нужно сделать так: от клиента принимать команды типа: "01C:\file.exe"#0 (что означает скачивание файла),
затем сервер посылает команду: "01C:\file.exe"#0"1024"#0 (команда на приём файла, размером 1024 байт).
После такого обмена информацией, клиент переводится в режим приёма файла, и записывает все принятые данные в MemoryStream, пока размер MS не будет равен 1024 байта... Если принялся весь файл, то клинт сохраняет файл, и снова переводится в режим приёма команд...
Правильно так ?
Я раньше использовал метод на подобии этого, и с ним у меня были ошибки ! Иногда файл не докачивался, иногда в коде файла были ошибки, иногда пакеты скелеивались, и клиент не мог отделить файл от команды и т.п. ерунда...
Подскажите как принимать и передавать данные такого типа без ошибок !?
Заранее благодарен.
← →
$hade (2003-09-19 06:43) [11]Иногда файл не докачивался, иногда в коде файла были ошибки
насколько я знаю - TCP - портокол с гарантированой доставкой пакетов - если ты читаешь 1024 - то 1024 тебе и придет и именно те которые ты посылал...
а если пакеты склеиваются - все таки это ошибки в твоем коде а не в протоколе....
поиши в сети описание протокола ICQ...если убрать всю лишнюю замутность - вполне неплохой протокол...как раз тебе подойдет...
← →
Verg (2003-09-19 07:37) [12]
> Плиз подскажите как разделять команды, если использовать
> пример протокола Slym"а ?
Какие проблемы?
В ASCII ориентированных протоколах разделителями обычно является ВКПС (#13#10, \n)
Короче я так ине понял к чему был приведен код программы, при том заведомо неработающей, да еще и свопросом "Как чтобы она надежно работала?"
Для начала сделайте, чтобы она работала хотя бы ненадежно :), а там посмотрим.
← →
Verg (2003-09-19 07:47) [13]
> Подскажите как принимать и передавать данные такого типа
> без ошибок !?
Вы что-то себе надумываете.
Какие ошибки имеются ввиду?
Искажения символов? Или exception-ы типа Access violation ?
Против первого типа применяется CRC (контрольная сумма)+Избыточное кодирование (коды Хемминга или Боуза-Чохвингема-Ховисайда, блин, наверняка неправильно всмпомнил) если уж вы прониклись таким недоверием к TCP/IP.
Как тут не вспомнить анекдот про старую деву, свечку и презерватив.
← →
Digitman (2003-09-19 08:09) [14]
> delpher_gray
с дост.долей уверенности могу предположить, что если ты используешь неблок.режим гнезда на стороне передатчика и если при этом не используешь событие OnWrite, то проблемы твои именно от этого возникают.
← →
Verg (2003-09-19 08:15) [15]
> при этом не используешь событие OnWrite, то проблемы твои
> именно от этого возникают
Пора бы это в ЧаВо или перед входом в форум-сети повесит :)
← →
Digitman (2003-09-19 08:32) [16]
> Verg
угу ... давно пора)
← →
Slym (2003-09-19 10:05) [17]Ну если боишься файл не докачать...
Делай типа как в POP3/smtp, там конец письма #13#10+"."+#13#10
UPLOAD file="c:\autoexec.bat";eof="#13#10.#13#10"
качай файл пока не встретишь комбинацию eof...
если файлы бинарные, то надо бы eof генерить для КАЖДОГО файла!
Например GUID,но проверять на вхождение этой строки в файл!
← →
Slym (2003-09-19 10:06) [18]А вообще как телнет работает... скока сказали принять столько и примет... все остальное ошибки юзера!
← →
delpher_gray (2003-09-19 11:13) [19]Ммммм да....
Видно глюки из-за события OnWrite...
Я толком так и не понял как с ним мозно передать файл со 100% гарантией :)
← →
delpher_gray (2003-09-19 11:40) [20]OnWrite тут по моему ни причём, ведь это событие возникает сразу после соединения, и только один раз за весь сеанс соединения !!
А я перед передачей MemoryStream"а, передавал и текстовые команды и они работали....
← →
Verg (2003-09-19 11:41) [21]
> Видно глюки из-за события OnWrite...
Бывает.
Народ вообще почему-то считает это событие каким-то ненужным, лишним что ли....
Между тем, начинать чего либо передавать в сокет после коннекта можно по только по условиям:
Для сервера : OnClientConnect && OnAccept && OnClientWrite
Для клиента : OnConnect && OnWrite
Мало того, при передаче данных (sendbuf) нужно анализировать рез-ат этой функции и если она вернула SOCKET_ERROR, а WSAGETLASTERROR = WSAEWOUDBLOCK, эту порцию информации надо сохранить и передавать только по наступлению следующего OnWrite.
А то напишут в OnConnect-е
Socket.SendText(S1);
Socket.SendText(S2);
Socket.SendText(S3);
Socket.SendText(S4);
Socket.SendText(S5);
.......
Socket.SendText(Sn);
А протом спрашивают: Почему глючит?
Тем не менее
function TCustomWinSocket.SendText(const s: string): Integer;
begin
Result := SendBuf(Pointer(S)^, Length(S));
end;
Получается сразу две ошибки!
← →
delpher_gray (2003-09-19 12:13) [22]А можно конкретный пример работы OnWrite ?
← →
Verg (2003-09-19 13:19) [23]
> А можно конкретный пример работы OnWrite ?
См. исходники
function TCustomWinSocket.SendStream(AStream: TStream): Boolean;
C:\Program Files\Borland\Delphi6\Source\Vcl\ScktComp.pas
Вникните.
Потом могу дать вот такие два куска:
function TBridge.SendData(var Buffer; Size : integer):integer;
var Bptr : pChar;
Sends : integer;
S : string;
begin
BPtr := pchar(@Buffer);
Result:=1; Sends:=0;
if Pending="" then
begin
while (Result>0) and (Sends<Size) do
begin
result:=ClientSocket1.Socket.SendBuf((Bptr+Sends)^,Size-Sends);
if Result>=0 then inc(Sends,Result);
end;
if Result=SOCKET_ERROR then
begin
if WSAGetLastError=WSAEWOULDBLOCK then
SetString(Pending, Bptr+Sends, Size-Sends);
end else begin result:=Sends; Pending:=""; end;
end else
begin
SetString(S, Bptr, Size);
Pending:=Pending+S;
Result:=0;
end;
end;
procedure TBridge.ClientSocket1Write(Sender: TObject;
Socket: TCustomWinSocket);
var S : string;
begin
if Pending<>"" then
begin
S:=Pending;
Pending:="";
SendData(Pchar(@S[1])^, length(S));
end;
end;
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.024 c