Форум: "Сети";
Текущий архив: 2005.11.27;
Скачать: [xml.tar.bz2];
ВнизКак отправить/принять через WinSock свыше 1gb? Найти похожие ветки
← →
NikNet © (2005-08-14 17:06) [0]У кого есть готовый код?
← →
забыл [кто-то зарегил мой ник] (2005-08-14 17:10) [1]а в чем сложности, милейший? ))))
← →
tesseract © (2005-08-14 17:15) [2]нареж кусками поменьше да и посылай
← →
panov © (2005-08-14 17:31) [3]http://www.delphimaster.ru/cgi-bin/forum.pl?n=4&search=WinSock
← →
NikNet © (2005-08-14 17:41) [4]Да мне бы типа SendLong и RecvLong!
Просто я много всякой ерунды наделал в проге
а все заново лень даи ещё вдруг что-то не так
сделаешь и все потом думаю что там не так :(
А код примерно у меня такой
0003 : Beep(Param);
0006 : ChatEnd(Param);
0007 : ChatID(Param);
...
и лист кода весит около 28kb вот и не охото все менять...
← →
NikNet © (2005-08-14 18:02) [5]Вот вобщем нашол но не фига непонил 8(
function wait_n_receive(ConServer:TSocket):string;
var
str,res:shortstring;
tmp:cardinal;
bsiz:Cardinal;
label z;
begin
str:="";
res:="";
tmp:=gettickcount;
repeat
z: bsiz:=recv(conserver,str[1],255,0);
if bsiz=-1 then
begin
bsiz:=wsagetlasterror;
if bsiz=WSAEWOULDBLOCK then
begin
res:="e!"#13;
break;
continue;
end else break;
end;
setlength(str,bsiz);
res:=res+str;
if not connected then break;
if tmp+40000 <= gettickcount then break;
if res="" then goto z;
until res[length(res)]=#13;
setlength(res,length(res)-1);
result:=res;
end;
(*
function wait_n_recvbuf(var b; siz:integer):integer;
var s:integer;
tmp:cardinal;
begin
s:=0;
tmp:=gettickcount;
repeat
bsiz:=recv(conserver,pointer(longint(@b)+s)^,siz,0);
if bsiz=-1 then begin
bsiz:=wsagetlasterror;
if bsiz<>WSAEWOULDBLOCK then break;
continue;
end;
if not connected then begin result:=0; exit; end;
if tmp+60000<=gettickcount then break;
s:=s+bsiz;
until s=siz;
result:=s;
end;
procedure sendfile(conserver:TSocket; fn:string);
var f:file;
buf:array[0..65535]of char;
fs,cnt:longint;
numread:integer;
s:string;
begin
AssignFile(f,fn);
{$I-}
Reset(f,1);
{$I+}
if ioresult<>0 then
begin
//senderror;
exit;
end;
fs:=filesize(f);
s:="sending?"+IntToStr(fs)+#13;
send(ConServer,s[1],length(s),0);
begin closefile(f); exit; end;
Begin
closefile(f);
exit;
end;
cnt:=0;
{ setwindowtext(mainwin,"Repeat Start");}
repeat
blockread(f,buf,8192,numread);
send(conserver,buf,numread,0);
cnt:=cnt+numread;
if wait_n_receive(conserver) <> "n!" then
begin closefile(f); exit; end;
until cnt>=fs;
closefile(f);
end;
← →
NikNet © (2005-08-14 18:03) [6]Кстати данные сжымаются так что всякие оконцовки не пройдут :(
← →
atruhin © (2005-08-14 19:03) [7]За такой код поубивавбы! Сотри его и не вздумай смотреть! В чем проблема то? Какая разница отправить 100 байт или 100 гб? При правильно написаном алгоритме ни какой. Чтобы помочь с кодом, скажи хоть что используешь, кмпоненты, winsock ...
← →
NikNet © (2005-08-14 19:24) [8]Да вот не могу отправить свыше одного гига карочи надо сделать две
процедуры и ф-ций которые бы принимали,/отправляли данные
и все это для WinSock!
Client использует TClientSocket
А Сервер на чистом API(WinSock)
Сервер должен передать данные (НЕ ФАЙЛ) размером 1gb
А Клиент должен принять их и выводить на экран или файл.
В общем, оптимизацию я предусмотрел! Так есть один алгоритм
быстрой передачи данных… Как с этим поконьчу скину.
Вот, в общем, то проблема как это реализовать.
← →
забыл [кто-то зарегил мой ник] (2005-08-14 19:44) [9]я не вижу проблемы. какая разница сколько передавать инфы? что именно передается то?
← →
забыл [кто-то зарегил мой ник] (2005-08-14 20:46) [10]А почему не реализовал клиент и сервер единообразно?
← →
NikNet © (2005-08-15 00:19) [11]#9
Передаётся огромный зашифрованый/сжатый блок
который оптимизированый!!! ЕСТЬ СИМВОЛЫ КОТОРЫЕ
Сокеты передают очень быстро!!!
Вот этот блок и надо по кусочкам передать
через WinSock!
#10
А на клиенте есть кучу наворотов!!!
← →
NikNet © (2005-08-15 00:33) [12]Люди хлтя бы покажите вобще как эти данные(свыше 1mb) передавать?
← →
Alexander Panov © (2005-08-15 01:41) [13]NikNet © (15.08.05 0:33) [12]
Точно так же, как и меньше мегабайта.
← →
NikNet © (2005-08-15 02:01) [14]Alexander Panov © (15.08.05 01:41) [13]
Точно так же, как и меньше мегабайта.
а как? покажите пример?
Между WinSock - SERVER и ClientSocket1 - Client?
Плизззз кому не составит труда...
← →
NikNet © (2005-08-15 03:15) [15]В общем, у меня между сервером и клиентом передача идет таким образом:
SERVER:
Case NumCmd of
0010 : // Вывести сообщение от администратора
Begin
MessageBox(hWnd,’Администратор запретил использовать эти ф-ций!’);
SendSock(ConSock,Coompress(’0010Ok’));
End;
end;
CLIENT:Data := Uncompress(RecvData); //Uncompress(RecvData) = 0010Ok
NumCmd := StrToInt(copy(Data,1,4));
Param := Copy(Data,5,Length(Data)-4);
Case NumCmd of
0010:
Begin
IF Param =’Ok’ Then
ShowMessage(‘Сообщение было отправлено’);
End;
end;
Caption:=IntToStr(NumCmd)+"-"+IntToStr(Length(Param));
← →
Slym © (2005-08-15 04:48) [16]NikNet © (14.08.05 18:02) [5]
Этому коду нельзя работать (если он работает)...
Ошибки:
1. break; continue;
2. Работа с неблокирующим сокетом без "сообщений", а опираясь на задержку ЦИКЛОМ!!! и на таймаут.
3. И как ты сЖЫмаешь? 100% ты используешь сжатие без оглядки на фрагментацию пакетов... От этого у тебя "случайные" сбои распаковки
← →
Digitman © (2005-08-15 08:49) [17]
> NikNet © (15.08.05 03:15) [15]
> SendSock(ConSock,Coompress(’0010Ok’));
надо понимать, процедура SendSock() у тебя данные размером ДО 1Гб передает успешно ? А проблемы возникают лишь при передаче данных размером более чем 1Гб ?
← →
NikNet © (2005-08-15 16:33) [18]Ну тогда покажите пример пожалуйста!!! Между
Клиентом и Сервером только что бы Сервер был на API(WinSock)
Прошу вас...
← →
Digitman © (2005-08-15 16:43) [19]ты не ответил на вопрос [17]
← →
NikNet © (2005-08-15 18:16) [20]#17
Она передает только 255 байт и все!!! По другому я не умею :(
← →
kami © (2005-08-15 18:50) [21]
> передает только 255 байт
Да вы цё?
Посмотрите ветку http://delphimaster.net/view/6-1122136315/
пост [11]
+ если разрешит Verg © - перешлю его пример.
← →
kami © (2005-08-15 19:14) [22]Уппс... не посмотрел, что сервер должен быть на API...
Но все равно - что мешает посмотреть исходники ServerSocket? & ТАК разжимать данные, которые неизвестно пришли полностью или нет, нельзя. У меня, например, на компьютере "стандартный" размер 8192 b.
немного структурируем код [5] :
procedure sendfile(conserver:TSocket; fn:string);
var f:file;
buf:array[0..65535]of char;
fs,cnt:longint;
numread:integer;
s:string;
begin
AssignFile(f,fn);// во-первых, лучше использовать FileStream
{$I-}
Reset(f,1);
{$I+}
if ioresult<>0 then
begin
//senderror;
exit;
end;
fs:=filesize(f);
s:="sending?"+IntToStr(fs)+#13;
send(ConServer,s[1],length(s),0);// размер файла узнать лучше FindFirstом, не будет ошибок при открытом файле
begin
closefile(f);
exit;// а здесь что? передали строку с размером и вышли ?
end;
Begin
closefile(f);
exit;// и еще раз вышли ?
end;
cnt:=0;
{ setwindowtext(mainwin,"Repeat Start");}
repeat);// а сюда как попадем? уже 2 раза быд Exit !
blockread(f,buf,8192,numread);// + f уже 2 раза закрыт !
send(conserver,buf,numread,0);
cnt:=cnt+numread;
if wait_n_receive(conserver) <> "n!" then
begin
closefile(f);
exit;
end;
until cnt>=fs;
closefile(f);
end;
← →
Slym © (2005-08-16 04:52) [23]У тебя сложности с АПИ? Зачем тебе АПИ?
Все программы используют АПИ ОС! Delphi предлагает удобную "упаковочку" этого АПИ. TServerSocket - АПИ в обектно-ориентированном виде.
← →
Digitman © (2005-08-16 08:24) [24]
> передает только 255 байт
приводи свой код
← →
NikNet © (2005-08-16 16:55) [25]
procedure SendSock(Socket: Integer; Str: string);//sending data
var
Buffer: Array [1..1024] of Byte;
i: Integer;
begin
FillChar(Buffer,SizeOf(Buffer),0);
if Length(Str)>1000 then Exit;
for i:=1 to Length(Str) do Buffer[i]:=Ord(Str[i]);
i:=WinSock.send(Socket, buffer, sizeof(buffer), 0);
if i=0 then SendSock(Socket, Str);
end;
function RecvSock(Socket: Integer): string;//reading data
var
Buffer: Array [1..100] of Byte;
i,RecB: Integer;
BufStr: String;
begin
BufStr := "";
RecB:=Recv(Socket, Buffer, SizeOf(Buffer), 0);
for i:=1 to RecB do
BufStr := BufStr + Chr(buffer[i]);
try Result := BufStr; except Result := ""; end;
end;
← →
Digitman © (2005-08-16 16:59) [26]
> NikNet © (16.08.05 16:55) [25]
прокомментируй каждую строчку - что и почему ты делаешь в ней ..
← →
NikNet © (2005-08-16 18:32) [27]А это не моё!!! и я не знаю что-то там вобще...
вот и спрашиваю пример... :=
← →
Slym © (2005-08-17 04:53) [28]Выбрось это... Это писал даже не студент первокурсник, а хуже восмикласник.
тоже самое:
procedure SendSock(Socket: Integer;const Str: string);
var i:integer;
begin
i:=WinSock.send(Socket,PChar(Str)^,Length(Str),0);
// глупая неправильная рекурсия... Stack overflow не беспокоил?
if i=0 then SendSock(Socket, Str);
//проще но не менее глупо и неправильно так
repeat
i:=WinSock.send(Socket,PChar(Str)^,Length(Str),0);
until i=0;
end;
function RecvSock(Socket: Integer): string;
var i: Integer;
begin
SetLength(result,1024);
i:=Recv(Socket, PChar(result)^,Length(result), 0);
SetLength(result,i);
end;
← →
Erik1 © (2005-08-17 15:22) [29]Еще можно глануть исходник Indy там только блокирующий режим используется, поэтому код проще.
← →
NikNet © (2005-08-17 18:14) [30]Slym © (17.08.05 04:53) [28]
Можно вопрос? Сколько байт этот код может отправить клиенту/серверу?
← →
atruhin © (2005-08-17 22:59) [31]прмерно так
Сервер - но исходник из другого проекта, поэтому смотри анализируй, делай
procedure TPortMapper.Execute;
var
i : integer;
TimeCr : TDateTime;
IT : TInternalThread;
FAddr: TSockAddrIn;
begin
GV^.EndWorkEvent:=CreateEvent(nil,true, false, nil);
//************************************************ // Слушающий поток
FListenSocket := socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if FListenSocket = INVALID_SOCKET then begin
MessageClient(msgWSAError, WSAGetLastError);
end else begin
FAddr.sin_family := PF_INET;
FAddr.sin_addr.s_addr := INADDR_ANY;
FAddr.sin_port := htons(GV^.ListenPort);
bind(FListenSocket, @FAddr, SizeOf(FAddr));
listen(FListenSocket, 100);
AcceptThread := TAcceptThread.Create(FListenSocket, GV);
//************************************************
while not Terminated do begin
Sleep(10);
end;
end;
end;
procedure TAcceptThread.Execute;
var
FAddr: TSockAddrIn;
Len: Integer;
IntPort : PInternalPort;
begin
while not Terminated do begin
New(IntPort);
Len:=SizeOf(FAddr);
IntPort^.Port:=Accept(FListenSocket,FAddr,Len); // Подключился новый клиент
if IntPort^.Port <> INVALID_SOCKET then begin
IntPort^.Time := Now;
try
GV^.IntPorts.Add(IntPort);
except
end;
end else begin
Dispose(IntPort);
exit;
end;
end;
end;
procedure TInternalThread.Complete;
const
MAX_PACKET_SIZE = 4096*2;
var
Hs : array [0..3] of THandle;
WaitResult : DWord;
EvCount : integer;
NetworkEvents:TWSANetworkEvents;
function DataRead(Sct : TSocket; var Data : TData; var LenData : integer) : integer;
var
Len : integer;
buff : array [0..MAX_PACKET_SIZE] of char;
begin
Len := Recv(Sct, buff[0], MAX_PACKET_SIZE, 0);
Result := Len;
if (Len = SOCKET_ERROR)
then begin MessageClient(msgWSAError, WSAGetLastError); exit; end;
if (LenData = 0)and(Len > 0)
then if Sct = InternalSocket
then IsInternalRead(TData(@buff), Len, Len)
else IsExternalRead(TData(@buff), Len, Len);
if Len > 0 then begin
ReallocMem(Data, LenData + Len);
Move(Buff[0], Data[LenData], Len);
inc(LenData, Len);
if LenData > BufferSizeOut then MessageClient(msgBufferSizeOut, 0);
if LenData <> Len
then if Sct = InternalSocket
then IsInternalRead(Data, LenData, Len)
else IsExternalRead(Data, LenData, Len);
end;
if SocketError then Result := -1;
end;
begin
SocketError := false;
fExternalSocket := INVALID_SOCKET;
fCurrHost := GV^.RemoteAddr;
fCurrPort := GV^.RemotePort;
Redirect := fCurrHost <> "";
fInternalData := nil;
fExternalData := nil;
fInternalLen := 0;
fExternalLen := 0;
EvCount := 2;
fTimeOut := AliveTimeout;
Hs[0] := GV^.EndWorkEvent;
Hs[1] := WSACreateEvent;
Hs[2] := WSA_INVALID_EVENT;
repeat
WSAEventSelect(InternalSocket, Hs[1], FD_READ or FD_CLOSE); // ожидаем внутеренний сокет
if EvCount = 3 then begin
WSAEventSelect(ExternalSocket, Hs[2], FD_READ or FD_CLOSE); // внешний
end;
WaitResult := WaitForMultipleObjects(EvCount, @Hs[0], false, fTimeOut*1000);
case WaitResult of
WAIT_FAILED, // неправильный вызов функции (неверный описатель?)
WAIT_OBJECT_0 + 0 : break; // Окончание работы
WAIT_TIMEOUT: begin
{$ifdef pmdebug}LineInLog("TimeOut - " + inttostr(NumberThread));{$endif}
MessageClient(msgRecvTimeout, 0);
break;
end;
WAIT_OBJECT_0 + 1 : begin
WSAEnumNetworkEvents(InternalSocket, Hs[1], @NetworkEvents);
if NetworkEvents.lNetworkEvents and FD_Read>0 then
if NetworkEvents.iErrorCode[FD_Read_Bit]=0 then begin // Пришли данные
if DataRead(InternalSocket, fInternalData, fInternalLen) < 0 then break;
if (ExternalSocket <> INVALID_SOCKET)and(Hs[2] = WSA_INVALID_EVENT) then begin
Hs[2] := WSACreateEvent;
EvCount := 3;
end;
end else break;
if NetworkEvents.lNetworkEvents and FD_Close>0 then begin
while DataRead(InternalSocket, fInternalData, fInternalLen) > 0 do ;
break;
end; {}
end;
WAIT_OBJECT_0 + 2 : begin
WSAEnumNetworkEvents(ExternalSocket, Hs[2], @NetworkEvents);
if NetworkEvents.lNetworkEvents and FD_Read>0 then
if NetworkEvents.iErrorCode[FD_Read_Bit]=0 then begin // Пришли данные
if DataRead(ExternalSocket, fExternalData, fExternalLen) < 0 then break;
end else break;
if NetworkEvents.lNetworkEvents and FD_Close>0 then begin
while DataRead(ExternalSocket, fExternalData, fExternalLen) > 0 do ;
break;
end;
end;
end;
until SocketError;
EndConnect; // Здесь делаем лог.
if Hs[1] <> WSA_INVALID_EVENT then WSACloseEvent(Hs[1]);
if Hs[2] <> WSA_INVALID_EVENT then WSACloseEvent(Hs[2]);
if ExternalSocket <> INVALID_SOCKET then begin
shutdown(ExternalSocket, SD_BOTH);
CloseSocket(ExternalSocket);
fExternalSocket := INVALID_SOCKET;
end;
if InternalSocket <> Invalid_SOCKET then begin
shutdown(InternalSocket, SD_BOTH);
CloseSocket(InternalSocket);
fInternalSocket := Invalid_SOCKET;
end;
if fExternalData <> nil then FreeMem(fExternalData);
if fInternalData <> nil then FreeMem(fInternalData);
{$ifdef pmdebug} LineInLog("Disconnect - "+IntToStr(NumberThread)); {$endif}
end;
но это кусок из портмаппера т.е. задача другая :) но вызовы процедур и работу с данными можно посмотреть. Писать тебе пример здесь вряд ли кто будет, это денег стоит Что непонятно спроси здесь.
← →
NikNet © (2005-08-17 23:38) [32]Erik1 © (17.08.05 15:22) [29]
atruhin © (17.08.05 22:59) [31]
Спасибо!!!
Если вас не затруднит :) НЕ могли бы помочь сделать
SendLong то есть передача длиных сообщений и RecvLong
Я думаю это не только решит мою проблему но многих других...
:)
← →
Eraser © (2005-08-17 23:41) [33]NikNet © (17.08.05 23:38) [32]
http://rentacoder.com/
← →
atruhin © (2005-08-18 00:20) [34]Могу но не буду. Я привел кусок проекта смотри, читай хелп, будут вопросы спрашивай. Там кое что лишнее, элементарного нет, смотри суть.
procedure TAcceptThread.Execute;
не правильная. заметил сейчас, остаток от пула потоков :))
смотри прием, передачу. ДУМАЙ.
← →
NikNet © (2005-08-18 17:21) [35]Все сделал!!! Это было проще простого !!!
Спасибо ВСЕМММММММ!!!
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2005.11.27;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.015 c