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

Вниз

Мастера, посмотрите вот так файлы через Socket перешлются?   Найти похожие ветки 

 
F1   (2002-10-23 11:45) [0]

К сожалению протестировал только в локальной(но ООчень медленной) сети. Вродебы сбоя не дало, но может быть я еще что-то не учел?

И еще попутно вопросик: Если к серверу подключены несколько клиентов, я так понял, пакеты будут приходить как-попало. Нужно наверное на каждого клиента завести record с буфером и дополнительной инфой, а потом по socket определять от кого пакет? Или есть что-то более оригинальное?

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
p:array of Byte;
FSize,Index,DeltaIndex:Integer;
F:File;
Tick:DWORD;
begin
AssignFile(F, Edit1.Text);
Reset(F,1);
FSize:=FileSize(F);
SetLength(p,FSize);
BlockRead(F,p[0],FSize);
ClientSocket1.Socket.SendBuf(FSize,SizeOf(FSize));
Index:=0;
repeat
DeltaIndex:=ClientSocket1.Socket.SendBuf(p[Index],FSize-Index);
if DeltaIndex=0 then
begin
Tick:=GetTickCount;
repeat
Application.ProcessMessages;
until GetTickCount-Tick>100;
end;
Index:=Index+DeltaIndex;
ProgressBar2.Position:=Index*100 div FSize;
until Index>=FSize;
StatusBar1.Panels.Items[0].Text:="Send "+IntToStr(FSize);
CloseFile(F);
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
S:String;
BufLen:Integer;
Buf:Array of Byte;
begin
if Reading then
begin
BufLen:=Socket.ReceiveLength;
if BufLen>NLength then BufLen:=NLength;
SetLength(Buf, BufLen);
BufLen:=Socket.ReceiveBuf(Buf[0], BufLen);
NLength:=NLength-BufLen;
St.WriteBuffer(Buf[0], BufLen);
if NLength=0 then
begin
StatusBar1.Panels.Items[1].Text:="


 
Digitman   (2002-10-23 12:10) [1]

А что принципиально изменилось у тебя в логике передатчика ?
imho, ничего.
по-прежнему пытаешься послать сразу весь файл
по-прежнему не обрабатываешь результат SendBuf = -1


 
F1   (2002-10-23 12:24) [2]

Digitman !

Согласен, ступил, я имел ввиду вот это:

if DeltaIndex<=0 then
begin
Tick:=GetTickCount;
repeat
Application.ProcessMessages;
until GetTickCount-Tick>100;
end;

Я пытаюсь послать весь файл, но ведь потом я смотрю сколько я реально послал?!

Если файл отошлется, то DeltaIndex = FSize, а если нет, то то я подожду и опять попробую остаток запихать. Или я опять что-то неправильно понял (с сетью первый раз работаю)?!!!


 
Digitman   (2002-10-23 12:51) [3]

Любой поток двоичных данных (каковым являются и имя файла и его содержимое) необходимо посылать блоками, размер которых не превышает размера буфера передачи гнезда.

Размер буфера передачи гнезда (тек.размер по-умолчанию) определяется вызовом Winsock-ф-ции GetSockOpt() с опцией SO_SNDBUF.

Попытка передачи каждого блока должна сопровождаться анализом результата вызванного SendBuf()-метода :

- если Result >= 0, передача очер.блока считается полностью или частично успешной;
позиция в исх.потоке передаваемых данных смещается на размер Result для подготовки к передаче след.блока (если есть еще данные)

- если Result = -1, передача очер.блока считается полностью неуспешной;
в случае асинхронного неблокирующего режима необходимо повторить передачу того же блока, дождавшись первого же ближайшего по времени события OnWrite()


 
F1   (2002-10-23 13:34) [4]

Digitman!!!
А в чем проблема, если я ПЫТАЮСЬ послать блок больше допустимого?! Меня ведь SendBuf все равно обламает! Результат SendBuf я анализирую.
При результате=0 или -1 я жду 100 Tick-ов и потом повторяю.

Согласен, что правильней(побыстрее по крайней мере) будет вот так:

if DeltaIndex<=0 then
begin
Tick:=GetTickCount;
Writing:=False;
repeat
Application.ProcessMessages;
until Writing;

procedure TForm1.ClientSocket1Write(Sender: TObject;
Socket: TCustomWinSocket);
begin
Writing:=True;
end;

Теперь-то, надеюсь, все правильно?! Или еще какой-то геморой может быть??? (Помимо обработки ошибок)

P.S. Спасибо за то что поставил на путь истинный. А то уже запарился - пишу и тестирую на одной машине, все работает, перехожу на сеть - glookiii!!!


 
Digitman   (2002-10-23 14:47) [5]

> А в чем проблема, если я ПЫТАЮСЬ послать блок больше допустимого?!

Буфер передачи-то - не резиновый ! Он имеет строго определенный размер.

> Меня ведь SendBuf все равно обламает! Результат SendBuf
> я анализирую.
> При результате=0 или -1 я жду 100 Tick-ов и потом повторяю.

А что толку повторять ? Поскольку буфер имеет строго определенный размер, больше этого размера он не примет данных - сколько ни пытайся.

По-умолчанию, скажем, он = 8к, а ты "тычешь" в него целых 8м

Пойми, буфер - это очередь ! А очередь имеет строго опред.размер.


Посмотри реализацию метода TCustomWinSocket.SendStreamPiece() - все это сразу станет понятным.


 
F1   (2002-10-23 15:08) [6]

> Пойми, буфер - это очередь ! А очередь имеет строго опред.размер.

Чето я опять не понял -

Если пытаешься писАть в буфер больше чем положено, лишнее все равно откинется (пример ведь работает в медленной сети на разных машинах). Так зачем заморачиваться с разбивкой (кроме экономии памяти на буфере), если TCP/IP возьмет сколько сможет и скажет, что остальное лишнее, и я это как нужно обработаю? Тем более, что даже если посылать по 8к, то не факт, что буфер будет пустой и в буфер поместятся все данные(все равно проверять придется).

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

Я ведь не сразу повторяю, а через некоторое время, за которое буфер может ОСВОБОДИТСЯ, т.к. данные ОТПРАВЯТСЯ.

> По-умолчанию, скажем, он = 8к, а ты "тычешь" в него целых 8M

Он ведь лишнего-то все равно НЕ ВОЗЬМЕТ. Не зря ведь SendBuf возвращает сколько он взял!!!

Или я опять торможу и что-то не понимаю????????????


 
Digitman   (2002-10-23 15:24) [7]

ты вообще в состоянии анализировать код чужой ?
Борланд, считаешь, чушь городит, если реализует это именно таким образом ?


function TCustomWinSocket.SendStreamPiece: Boolean;
var
Buffer: array[0..4095] of Byte;
StartPos: Integer;
AmountInBuf: Integer;
AmountSent: Integer;
ErrorCode: Integer;

procedure DropStream;
begin
if FDropAfterSend then Disconnect(FSocket);
FDropAfterSend := False;
FSendStream.Free;
FSendStream := nil;
end;

begin
Lock;
try
Result := False;
if FSendStream <> nil then
begin
if (FSocket = INVALID_SOCKET) or (not FConnected) then exit;
while True do
begin
StartPos := FSendStream.Position;
AmountInBuf := FSendStream.Read(Buffer, SizeOf(Buffer));
if AmountInBuf > 0 then
begin
AmountSent := send(FSocket, Buffer, AmountInBuf, 0);
if AmountSent = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if ErrorCode <> WSAEWOULDBLOCK then
begin
Error(Self, eeSend, ErrorCode);
Disconnect(FSocket);
DropStream;
if FAsyncStyles <> [] then Abort;
Break;
end else
begin
FSendStream.Position := StartPos;
Break;
end;
end else if AmountInBuf > AmountSent then
FSendStream.Position := StartPos + AmountSent
else if FSendStream.Position = FSendStream.Size then
begin
DropStream;
Break;
end;
end else
begin
DropStream;
Break;
end;
end;
Result := True;
end;
finally
Unlock;
end;
end;


 
F1   (2002-10-23 15:35) [8]

Анализировать чужой код я-то в состоянии. Может быть они на промежуточном буфере экономят, а у меня его вообще не, так что мне не на чем экономить. Тем более, что если я делаю что-то не так, как Борланд, то это не означает, что я не прав!!!


 
Digitman   (2002-10-23 15:39) [9]

Да как угодно. Не хочешь вникать - уговаривать не собираюсь. Оно мне не надо.


 
Polevi   (2002-10-23 15:41) [10]

чего ты уперся, тебе дело советуют
и вообще твой способ с ТикКаунт это гм.. - пытаться снова послать данные надо в следующем OnWrite
если Борланд для тебя не авторитет - почитай хелп на WSAAsyncSelect, там все написано


 
F1   (2002-10-23 15:53) [11]

Да ладно Вам, расслабьтесь, все я понял, просто мне никто так и не объяснил чем плохо SendBuf(Buf, Size > чем нужно), кроме того, что Борланд так делает. Ведь протокол TCP/IP делал Microsoft и никому не сказал, как он его делал, даже Борланду.

В любом случае всем ООГГРРООММННООЕЕ СПАСИБО, особенно Digitman все получилось и работает !!!!!!!!!!


 
Polevi   (2002-10-23 16:00) [12]

>протокол TCP/IP делал Microsoft
а интернет Билл Гейтс придумал


 
Digitman   (2002-10-23 16:00) [13]

>>никто так и не объяснил чем плохо SendBuf(Buf, Size > чем нужно)

да чего тебе объяснять ? ты ж уперся в свои 100% )...

да ничем не плохо !
но - только при синхронном блокирующем режиме.
А ты, видимо, и разницы не понимаешь..

Да это не самое страшное - ты ведь вникнуть не хочешь, вот ведь беда) ..
начал вместо этого ерунду всякую нести про то, что MS "никому не сказал, как он его делал"



 
F1   (2002-10-23 17:11) [14]

Digitman!

>да ничем не плохо !
>но - только при синхронном блокирующем режиме.
>А ты, видимо, и разницы не понимаешь..

Так у меня режим асинхронный неблокирующий, т.е я делаю send и моя прога и не дожидаясь передачи данных продолжает работать, а протокол сам со свом буфером разбирается.

>Да это не самое страшное - ты ведь вникнуть не хочешь, вот ведь >беда) ..
>начал вместо этого ерунду всякую нести про то, что MS "никому >не сказал, как он его делал"

Вникнуть-то я хочу, а на счет ерунды, это я так ;)))

Ладно, в итоге я посылаю кусками, и обрабатываю OnWrite.
А можно ли размер этого самого буфера как-то увеличить, и вообще следует ли это делать. Мне кажется для локальной сети 8к маловато.


 
Digitman   (2002-10-23 17:27) [15]


> у меня режим асинхронный неблокирующий, т.е ...
> протокол сам со свом буфером разбирается.


Вот он и разберется.. особенно когда попытаешься разнести клиента и сервера по разным подсетям ... просто выкинет тебя SendBuf() с отказом -1 при попытке записать в буфер передачи больше данных, чем возможно В ДАННОЙ сет.среде - и всех делов ... вот и все твои 100% будут)

При блокирующем же режиме это "фокус" вполне может и пройти, потому как ответственность за обработку внутренних событий внутренних же буферов берет на себя ядро Winsock. Действует же оно в этом случае точно так же - делит вх.поток на блоки и пополняет ими очередь по мере необходимости... но для прикладной программы это попросту незаметно, "прозрачно"


> можно ли размер ... буфера ... увеличить


Можно. Но в подавляющем большинстве случаев не нужно. Смысл каков ? Ведь соответствующий буфер, куда будет считываться очер.блок (передаваемый затем как параметр на вход SendBuf) тоже - очевидно - придется увеличить ! Зачем бестолково расходовать ресурсы системы ? Быстрей передача все равно не получится : эффективность и надежность передачи данных по трансп.каналу гораздо более зависит от множества иных факторов, характерных для конкретной сетевой среды.



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

Форум: "Сети";
Текущий архив: 2002.12.19;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.01 c
1-61531
dkDimon
2002-12-08 01:34
2002.12.19
System Tray


7-61841
NS
2002-10-12 10:31
2002.12.19
электронный ключ


14-61759
ЮРИЙ_К
2002-11-20 16:21
2002.12.19
Удалить счетчик шарной программы


1-61513
_saha_
2002-12-05 11:00
2002.12.19
Создание класса


3-61408
Tankist
2002-12-03 13:47
2002.12.19
Mysql





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский