Форум: "Сети";
Текущий архив: 2002.08.08;
Скачать: [xml.tar.bz2];
Внизsocket Найти похожие ветки
← →
CrazyTemo (2002-05-22 17:53) [0]как синхронизавать socket? то есть как контролиравать передачу дааных? например когда я посилаю текст, сервер получает все в месте, а я хочу получать каждую строку отделно
← →
KPOT (2002-05-22 18:46) [1]Читай по одному символу до контрольного знака
← →
cyborg (2002-05-23 09:18) [2]CrazyTemo Ничего не нужно контролировать, сокет сам уже всё контролирует, вот вставь себе в программу такой код:
Const Delitel : String = #13#10;
{Разделитель строк, добавляется в конец отсылаемых данных, можно написать любой, какой нравится}
---------
{Процедура обработки мессаг S-передаваемая строка,
Socket - Передаваемый сокет откуда пришла мессага}
Procedure Process_Message(Var S : AnsiString;Var Socket: TCustomWinSocket);
Begin
{Обрабатываем здесь полученные данные}
End;
procedure TMyForm.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
Var S,_S : AnsiString;
I : Integer;
begin
S:=Socket.ReceiveText;
I:=0;
Repeat {Разделяем строку, если одновременно пришло несколько}
I:=Pos(Delitel,S); {Ищем радлелитель Delitel}
if I<>0 then {Если найден делитель, тогда ... Если не найден, то ты не добавил в конце отсылаемой строки Delitel !}
Begin
_S:=Copy(S,1,I-1);{Копируем одну мессагу}
Delete(S,1,I+Length(Delitel)-1);
{Удаляем уже скопированную мессагу}
Process_Message(_S,Socket);
{Процедура обработки мессаг где _S наша выделенная мессага}
End;
Until I=0;
end;
{Пример отправки мессаг}
Socket.SendText("Ку ку!"+Delitel); {Важно добавлять в конце каждой отправляемой строки разделитель строк Delitel}
-----------------
Всё должно работать :-) ...
← →
Digitman (2002-05-23 11:01) [3]>cyborg
Это не будет работать ожидаемым образом. Неверно представляешь себе логику метода ReceiveText().
← →
Fredericco (2002-05-23 16:51) [4]cyborg © >> Если на том конце всегда добавлять #13#10 если нет физических сбоев или резкого зависания системы, то на другом конце ты всегда увидишь #13#10.
← →
cyborg (2002-05-23 20:02) [5]Digitman ©
А что за работа неожиданным образом?
Однако работает :-). У меня всё прекрасно делит. Хотя всё может быть. Расскажите поподробнее.
Fredericco ©
:-) На том и состоит код, что разделитель видно и по нему разбивается, т.е. не понял смысл ваших слов.
А вот сбои :-), это просто беда ...
← →
Malder (2002-05-23 21:28) [6]Я тоже не понял претензии Digitman"а
← →
Donal_Graeme (2002-05-24 09:18) [7]2 cyborg: у тебя не предусмотрено, что сообщения могут быть разбиты. т.е. ты отправляешь "абвгд#13#10" а получатель сперва получает "аб" а потом "вгд#13#10".
← →
Digitman (2002-05-24 09:43) [8]Пусть передающая сторона выполнила следующее :
1. Socket.SendText("Ку ку!"+Delitel);
2. Socket.SendText("Ку ку!"+Delitel);
3. Socket.SendText("Ку ку!"+Delitel);
где
Delitel = #13#10
Тогда не исключена ситуация, что в момент возникновения на принимающей стороне самого первого (с момента старта приема) события TCustomWinSocket.OnRead() в буфере приема гнезда будет доступен след.поток данных :
Ку ку!#13#10 #0Ку ку!#13#10 #0Ку ку!#13#10 #0
всего - 27 символов; в реальности может быть и меньше из за особенности TCP-транспорта
Согласно приведенному коду от <cyborg © (23.05.02 09:18)> первая же инструкция, выполняемая в теле OnRead(), это
S:=Socket.ReceiveText;
Теперь посмотрим, что "творится" в теле метода ReceiveText() :
function TCustomWinSocket.ReceiveText: string;
begin
//получить ожидаемый приемником размер данных
//ReceiveBuf(Pointer(nil)^, -1) <= 27
//и установить для результирующей Ansi-строки длину,
//равную этому (максимально возможному в дан.момент) значению
SetLength(Result, ReceiveBuf(Pointer(nil)^, -1));
//прочитать из буфера приема и скопировать в буфер результ.строки
// действительно доступные данные размером, возвращенным
//при вызове ReceiveBuf(Pointer(Result)^, Length(Result));
//скорректировать длину результ.строки так, чтобы ее буфер занимал в памяти ровно столько, сколько в действительности удалось принять
SetLength(Result, ReceiveBuf(Pointer(Result)^, Length(Result)));
end;
Не исключено, что по завершению метода TCustomWinSocket.ReceiveText() результ.строка будет содержать следующее :
Ку ку!#13#10 #0Ку ку!#13#10 #0Ку ку!#13#10 #0 #0
Обратим внимание, что в конце стоят 2 символа-терминатора, последний из которых добавлен автоматически при вызове SetLength()
Теперь смотрим, что происходит при выполнении собственно присваивания в строчке
S:=Socket.ReceiveText;
Первым же делом выполняется определение актуального (!) размера строки, возвращенной методом ReceiveText() для выделения необходимого размера памяти под буфер строки S; актуальный размер Ansi-строки будет равен числу байт от начала строкового буфера до первого встреченного символа-терминатора #0
В принятой строке позиция первого терминатора равна 9, поэтому размер строки S будет установлен равным 8, а ее содержимое равным"Ку ку!"#13#10
.
Остальные (следующие за первыми девятью) 18 символов копируемого при присвоении буфера исходной строки будут проигнорированы и безвозвратно утеряны !! И никакие "специальные" терминаторы Delitel не могут изменить эту ситуацию.
Резюме : надежный (без потерь) прием данных, имеющих текстовый формат, при непрерывном сеансе работы гнездового соединения в поточном режиме на принимающей стороне не может быть осуществлен с помощью метода ReceiveText(). Для реализации поточного приема текстовых строк в рамках одного и того же соединения следует применять иные способы работы с буфером приема, не задействующие стандартные строковые ф-ции Object Pascal"я.
С учетом всех этих замечаний поточные прием/передача текста должны быть организованы в самом простом случае, например, след.образом :
1. Передача
var
S: String;
len: Integer;
...
S := "Ку ку!";
len := Length(S);
...
//передача размера передаваемых следом стр.данных
Socket.SendBuf(len, SizeOf(len));
//передача собственно стр.данных
Socket.SendBuf(@S[1], len);
//снова - передача размера передаваемых следом стр.данных
Socket.SendBuf(len, SizeOf(len));
//снова - передача собственно стр.данных
Socket.SendBuf(@S[1], len);
//снова - передача размера передаваемых следом стр.данных
Socket.SendBuf(len, SizeOf(len));
//снова - передача собственно стр.данных
Socket.SendBuf(@S[1], len);
... и т.д. ....
2. Прием
procedure TMyForm.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
Var
cnt
len: Integer;
buf: PChar;
S: String;
begin
cnt := Socket.ReceiveBuf(len, SizeOf(Len));
if cnt < SizeOf(Len) then begin
Socket.Close;
... генерация исключения рассинхронизации приема ...
end;
SetLength(S, len);
buf := PChar(S);
while len > 0 do begin
cnt:= Socket.ReceiveBuf(buf^, Len);
if cnt = 0 then begin
Socket.Close;
... генерация исключения рассинхронизации приема ...
end;
Dec(len, cnt);
Inc(buf, cnt);
end;
Process_Message(S,Socket); //передача принятой строки на обработку
end;
← →
cyborg (2002-05-24 10:49) [9]Digitman © Я думаю вы ошибаетесь.
Тот способ, который я привёл, я использую не для простоой передачи строки, а строки с коммандами. Команды это байты, которые могут иметь и значение 0 и этим способом всё прекрасно передаётся и получается. Я думаю (может ошибаюсь) AnsiString имеет такой же формат как и обычная Паскалевская строка, только размером до 2-х гигабайт и она не заканчивается символом #0.
В моём чате передаётся такая строка:
1-й байт - команда
2-й байт - дополнительная команда
3-й байт - Номер картинки
4-7 байты - Integer - Цвет.
С 8-ого идёт строка сообщения
И все эти байты могут содержать нулевые значения. Особенно цвет, он как известно хранится в Integer который занимает 4 байта, а сам цвет состоит из 3-х байт, и первый в этом значении всегда #0 (нулевой). И этим способом всё работает прекрасно! И при передаче никаких лишних #0 не прибавляется. Возможно вы говорите о ранних версиях Delphi, может там и работает так как вы сказали, но по крайней мере в Delphi6 всё прекрасно работает. Можете сами проверить.
← →
Crazytemo (2002-05-24 11:28) [10]izvinite ia po ruski ploxo pechataiu. ia nashol takoe reshenie, kogda otsilay odny stroky , jdu poka ne poluchu podtverjdenie i tolko potom posilau sleduyshuiu stroky. chto dumaeeto po etomy povodu?
vot primer:
Socket.sendtext("1 stroka");
while recevied<>true do
socket.receivetext;
Socket.sendtext("2 storka");
← →
Digitman (2002-05-24 11:40) [11]>cyborg
1. 6-ки у меня нет под рукой, поэтому сравнить реализации SendText() и ReceiveText() с версиями менее 6-й не могу. Но думаю, что и в 6-ке реализации этих методов содержат ту же логику, что и в предыдущих версиях. Приведи, пожалуйста, текст реализации одноименных методов в 6-ке, я сравню их и прокомментирую различия в функц-ти (если таковые будут).
2. Интересно, как это ты вообще умудряешься транслировать бинарные данные собственного формата методом, предназначенным исключительно для трансляции текстовых данных стандартного формата ?
В твоем примере я не увидел ничего кроме SendText()/ReceiveText(), т.е. только "чистый" текст и ничего более. Для любых же стороковых типов символ-терминатор #0 (байт/слово со значением 0) всегда обозначает логический конец текста, и все, что за терминатором, попросту отбрасывается и не принимается во внимание.
3. Твои абстрактным, не подтвержденным аргументами заявлениям о том, что то, что ты здесь привел (с точностью до назначения каждой строчки приведенного кода), работает так как это и ожидается по логике, я противопоставил достаточно детальный разбор механизма работы упомянутых тобой методов. Укажи мне аргументированно на ошибки или несуразицы в изложенном мной - и я немедленно и публично сниму перед тобой шляпу, а автор получит точное представление того, как это д.б. реализовано и как работает в действительности. И да восторжествует истина !))))
← →
cyborg (2002-05-24 13:02) [12]Я согласен, что этот способ не идеальный, и подходит только для передачи строк, ведь Delitel может совпасть с данными :-) и получится фигня.
В этом случае нужно использовать SendBuf и ReceiveBuf добавляя в начало размер отсылаемых данных, что бы потом сравнивать пришедшее...
Но идея та же ... Получать данные в SocketRead Смотреть что пришло, если нужно - разделить, если недопришло - дополучить, а потом всё передавать функции Process_Messages ...
← →
Digitman (2002-05-24 13:14) [13]>cyborg
Да не то что "не идеальный" ! Вообще не подходит. А ты тем не менее совет даешь автору...
← →
cyborg (2002-05-24 13:27) [14]Const
Delitel : String =#13#10; {Разделитель передаваемых строк с помощью которого узнаётся сколько строк прислали}
{Команды Command:}
CDisconnect = 0; {Клиент сообщает что отсоединяется}
CPassword = 1; {Пароль от клиента}
CName = 2; {Имя клиента}
CMessage = 100; {Пришла обычная мессага для всех}
CPrivate = 101; {Мессага для конкретного IP}
CClientConnect = 200; {Подключился клиент}
CClientDisconnect = 201; {Отключился клиент}
CLive = 255; {Клиент напоминает о себе что в сети, должно приходить каждые N секунд}
Function CodeChatString(Const Command,SecondCommand,Face : Byte;
Const Color : Integer; Const Messaga : AnsiString) : AnsiString; {Все комманды в одну строку}
Var S : AnsiString;
IntS : array[0..3] of char;
Begin
IntS:=#0#0#0#0;
Move(Color,IntS,4);
S:=Chr(Command)+Chr(SecondCommand)+Chr(Face)+IntS[0]+IntS[1]+IntS[2]+IntS[3]+Messaga;
Result:=S;
End;
Procedure DecodeChatString(StringToDecode : AnsiString;
Var Command,SecondCommand,Face : Byte;
Var Color : Integer;Var Messaga : AnsiString); {Расшифровать коммандную строку}
Var
S : AnsiString;
I : Integer;
Begin
S:=StringToDecode;
Command:=Ord(S[1]);
SecondCommand:=Ord(S[2]);
Face:=Ord(S[3]);
Move(S[4],I,4);Color:=I;
Delete(S,1,7);
Messaga:=S;
End;
{Эта та самая Process_Messages}
Procedure _Messages(Var _S : AnsiString;Var Socket: TCustomWinSocket);
{Обработать сообщение}
Var
S : AnsiString;
Command,SecondCommand,Face : Byte;
Color : Integer;
Messaga : String;
ListItem : TListItem;
_Data : PData;
I : Integer;
Begin
S:=_S;
DecodeChatString(S,Command,SecondCommand,Face,Color,Messaga); {Расшифровать коммандную строку}
Case Command of
CDisconnect : Begin
End;
CPassword : Begin
End;
CName : Begin
GetMem(_Data,SizeOf(ZData));
_Data.Name:=Messaga;
_Data.Color:=Color;
_Data.Face:=Face;
_Data.Tag:=SecondCommand;
ListItem:=MyForm.ListBoxChaters.Items.Add;
ListItem.ImageIndex:=Face;
ListItem.Caption:=Messaga;
ListItem.Data:=_Data;
// MyForm.ListBoxChaters.Items.Add(Messaga);
_DelLines;
MyForm.EditChat.SelAttributes.Color:=clFuchsia;
MyForm.EditChat.Lines.Add("-> ("+TimeToStr(Time)+") в чате: "+Messaga);
_ScrollWindow;
End;
CMessage : Begin
_DelLines;
MyForm.EditChat.SelAttributes.Color:=Color;
MyForm.EditChat.SelAttributes.Style:=[fsBold];
MyForm.EditChat.Lines.Add(Messaga);
_ScrollWindow;
End;
CPrivate : Begin
End;
CClientConnect : Begin
End;
CClientDisconnect : Begin
_Data:=Nil;
Repeat
_Data:=MyForm.ListBoxChaters.FindCaption(0,Messaga,True,False,False).Data;
if (_Data.Name=Messaga) and (_Data.Face=Face) and (_Data.Tag=SecondCommand) then
Begin
I:=MyForm.ListBoxChaters.FindData(0,_Data,False,False).Index;
MyForm.ListBoxChaters.Items.Delete(I);
FreeMem(_Data,SizeOf(ZData));
_Data:=Nil;
End;
Until _Data=Nil;
_DelLines;
MyForm.EditChat.SelAttributes.Color:=clFuchsia;
// MyForm.EditChat.SelAttributes.Style:=[fsBold];
MyForm.EditChat.Lines.Add("-> ("+TimeToStr(Time)+") вышел из чата: "+Messaga);
_ScrollWindow;
End;
CLive : Begin
End
else Begin
End;
End; {case}
End;
procedure TMyForm.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
Var S,_S : AnsiString;
I : Integer;
begin
S:=Socket.ReceiveText;
I:=0;
Repeat {Разделяем строку, если одновременно пришло несколько}
I:=Pos(Delitel,S); {Ищем радлелитель Delitel}
if I<>0 then
Begin
_S:=Copy(S,1,I-1);{Копируем одну мессагу}
Delete(S,1,I+Length(Delitel)-1); {Удаляем уже скопированную мессагу}
_Messages(_S,Socket);{Процедура обработки мессаг где _S наша выделенная мессага}
End;
Until I=0;
end;
procedure TMyForm.Edit1KeyPress(Sender: TObject; var Key: Char);
Var S : String;
begin
if ClientSocket1.Active then
if Key=#13 then
if Edit1.Text<>"" then
Begin
Key:=#0;
S:=CodeChatString(CMessage,0,0, ClientColor.Brush.Color,Edit1.Text);
ClientSocket1.Socket.SendText(S+Delitel);
Edit1.Clear;
End;
end;
Вот вырезал из программы, не стал редактировать не нужные в примере функции, думаю и так поймёте.
Так как Delitel может совпасть с данным в дальнейшем всё это переделаю под SendBuf и ReceiveBuf, а так всё работает :-)
В Delphi6 так:
function TCustomWinSocket.SendText(const s: string): Integer;
begin
Result := SendBuf(Pointer(S)^, Length(S));
end;
function TCustomWinSocket.ReceiveText: string;
begin
SetLength(Result, ReceiveBuf(Pointer(nil)^, -1));
SetLength(Result, ReceiveBuf(Pointer(Result)^, Length(Result)));
end;
← →
cyborg (2002-05-24 13:30) [15]Если вы не верите что работает :-), то зайдите на мою пагу и скачайте рабочий чат http://www.buzuluk.ru/~cyborg
← →
cyborg (2002-05-24 13:40) [16]function TCustomWinSocket.SendText(const s: string): Integer;
begin
Result := SendBuf(Pointer(S)^, Length(S));
end;
Обратите внимание на Length(S), здесь S - String, а не PChar, так что отправляемое никак не имеет в конце #0.
--------
function TCustomWinSocket.ReceiveText: string;
begin
SetLength(Result, ReceiveBuf(Pointer(nil)^, -1));
SetLength(Result, ReceiveBuf(Pointer(Result)^, Length(Result)));
end;
Здесь ReceiveBuf, все работает с конкретным Pointer, а не ссылается на PChar который имеет в конце #0, так что и здесь никак не прибавляется #0.
← →
Digitman (2002-05-24 14:12) [17]>cyborg
Молодец !! Браво !! Не поддался на провокацию !)
Снимаю шляпу) .. Все, что я ожидал - приведение и анализ тобой в кач-ве контраргумента тела метода TCustomWinSocket.SendText().
Действительно, нуль-терминаторы не помещаются передатчиком в поток, поэтому принятой в OnRead() с пом.метода ReceiveText() строкой будет считаться все актуально доступные данные в момент выполнения метода. А вот все ли целиком строки, действительно и последовательно отправленные передатчиком, будут составлять целое содержимое полусенной приемником строки - это уже вопрос. В лок.сети еще можно как-то понадеяться на маловероятность ситуации с "разрывом" строк, но в глоб.сети такой фокус заведомо не прокатит - оч.часто приемник будет получать "рваные" на куски строки
← →
cyborg (2002-05-24 14:22) [18]Ещё прошу заметить что
SendText и ReceiveText этот те же самые SendBuf и ReceiveBuf, только размер не нужно указывать, так как они сами вычисляют размер строки.
А теперь так и хочется сказать :-)
Снимайте шляпы господа!
← →
cyborg (2002-05-24 14:28) [19]Ой запоздал с мессагой :-), набирал в оффлине, поэтому :-)).
Да, меня убедили, что нужно ещё и проверять на то, что полностью получено или оборванно, займусь как нибудь этим кодом, выложил пока в UBPFD тот, который я привёл. Потом глядишь и универсальный помещу, может кто и лучше сделает, чему я буду рад :-)
← →
Digitman (2002-05-24 15:08) [20]>cyborg
Рановато ты загордился, однако)
Нет, далеко не те же самые ! И дело даже не в автовычислении размера.
SendBuf/ReceiveBuf предназначены для передачи/приема ЛЮБЫХ бинарных данных, без привязки к конкретному формату.
А касаемо SendText/ReceiveText попробуй-ка в ЛВС и прокомментируй следующее :
var
s: string;
r: string;
..
s:= "Ку ку !";
s[3]:= #0;
ShowMessage(s);
...
Socket.SendText(S);
...
r:= Socket.ReceiveText;
ShowMessage(r);
Вопрос : s = r ? Почему ?
← →
Malder (2002-05-24 18:54) [21]А почему нет ?
← →
cyborg (2002-05-24 18:56) [22]Господи, это очередная ваша провокация?
Если да, то я так понимаю, что вы меня проверяете на знания :-).
Ну, а если нет, то я не понимаю зачем вам дали значёк мастера?
Значит вот что я сворганил
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp;
type
TfmHead = class(TForm)
Client: TClientSocket;
Server: TServerSocket;
procedure FormActivate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure ServerClientRead(Sender: TObject; Socket: TCustomWinSocket);
private
{ Private declarations }
public
{ Public declarations }
end;
var
fmHead: TfmHead;
implementation
{$R *.dfm}
procedure TfmHead.FormActivate(Sender: TObject);
Var
s: Ansistring;
begin
Server.Open;
Client.Open;
s:= "Ку ку !";
s[3]:= #0;
ShowMessage(s);
Client.Socket.SendText(S);
end;
procedure TfmHead.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Client.Close;
Server.Close;
end;
procedure TfmHead.ServerClientRead(Sender: TObject;
Socket: TCustomWinSocket);
Var
r: Ansistring;
begin
r:= Socket.ReceiveText;
ShowMessage(r);
end;
end.
Так действительно как будто не работает. Почему, скажу позже.
А вот теперь работает:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp;
type
TfmHead = class(TForm)
Client: TClientSocket;
Server: TServerSocket;
procedure FormActivate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure ServerClientRead(Sender: TObject; Socket: TCustomWinSocket);
private
{ Private declarations }
public
{ Public declarations }
end;
var
fmHead: TfmHead;
implementation
{$R *.dfm}
procedure TfmHead.FormActivate(Sender: TObject);
Var
s: Ansistring;
begin
Server.Open;
Client.Open;
s:= "Ку ку !";
s[3]:= #0;
ShowMessage(s);
Client.Socket.SendText(S);
end;
procedure TfmHead.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Client.Close;
Server.Close;
end;
procedure TfmHead.ServerClientRead(Sender: TObject;
Socket: TCustomWinSocket);
Var
r: Ansistring;
I : Integer;
begin
r:= Socket.ReceiveText;
For I:=1 to Length(r) do
if r[I]=#0 then r[I]:="X";
ShowMessage(r);
end;
end.
Так как в ShowMessage использует WinAPI, известно что все строки там передаются PChar-ами. И естественно на экран не выводится то, что после #0. Но стоит заменить в пришедшей строке #0 например на X то мы увидим, чтот вся строка пришла полностью.
Ну что, сделал я мастера :-)? Ну признайтесь ...
← →
Crazytemo (2002-05-25 08:10) [23]prblema zakluchaetsia isho vodnom, kto nebud iz vas probival posilat bolshoi fail ispolzuia sendtext? ia probival i polucaheetsia takaia vesh, programa zavisaet i potom windows krichit:))) mol ne xvataet operativnoi pamiati. mne ne nujno otsilat bolshie faili, no vsio ravno intersesno pochemu eto proisxodit
← →
cyborg (2002-05-25 09:19) [24]:-) Как уже сказали, SendText предназначен для посылки строк, а не файлов.
А винды при этом не зависают, а отсылают твой файл, при этом программа не работает, как бы зависла.
Используй для передачи данных SendBuf ReteiveBuf!
Если так уж хочется переслать SendText-ом, то дели файл на части, например по 500 байт, 1 килобайт, короче на твоё усмотрение, и в начале каждой строки вставляй размер отсылаемого блока и номер части файла, что бы потом при получении всё сложить. При полученнии читаешь из полученной строки размер и номер части файла, сравниваешь размер с пришедшими данными, если не совпало, сохраняешь что уже пришло, что бы при повторной загрузке качать не заново, а продолжить. Если всё пришло нормально, складываешь полученные участки в порядке, в котором указано в номере чати файла. Перед передачей, можно посылать название файла, который хочешь передать, если уже такой передавался и оборвался, посылаешь ответ, что такой то файл нужно передавать с такого то размера, та строкона получает эту команду и продолжает кидать тебе файл с места обрыва. А для точности передачи данных, можно придумать контрольную сумму, если не сомпала, то посылаешь что такой то (с номером участок) нужно заново прислать.
Надеюсь понял, что я понаписал :-)
← →
Crazytemo (2002-05-25 09:31) [25]eto ia ponimaiu vo pervix ia ne xochu ispolzovat senbuf, vo vtorix kogda otsialetsia text file tam tiriatsia simvol konca stroki i prixodetsia dobovliat #13#10 na konce kajdoi stroki , i vtretix problema ni vtom chto eta ne rabotaet , a v tom cto ne rabotaet na bolshix failax na malenkix bez problem. i isho sendtext toje samoe chto sendbuf, tak chtno kakoi smisl ispolzivat sendbuf?. u menia logika takaia otsialau stroky jdu potdtverjdenia i posilau sleduishii. to es problem ne daljno bit. tolko ne gavarite shas chto eto glupo posilat kajduio storky otdelno:))). poprobuite sami sdelat eto i uvidite,
← →
cyborg (2002-05-25 17:46) [26]Для текстовых файлов можно использовать этот способ пересылки построчно, читать строку, потом посылать, а что если строка в файле длинной ОГОГО?
SendText и SendBuf одно и тоже в смысле используемого метода, но не одно и то же для использования!
Есть ещё SendStream() предназначенный для передачи потока.
Короче итог: SendText для передачи файлов не подходит и использовать его так, просто глупо, когда есть специально предназначенные для этого вещи.
← →
Digitman (2002-05-27 08:54) [27]>cyborg
Да все нормально, не волнуйся)... Больше "провокаций" не будет)...
Все верно :
strlen(s) <> length(s),
так же как
strlen(r) <> length(r)
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2002.08.08;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.006 c