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