![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как отправить/принять через WinSock свыше 1gb? [D6]
NikNet © (2005-08-14 17:06:00)У кого есть готовый код?
NikNet (2005-08-18 17:21:00) [1]Все сделал!!! Это было проще простого !!!
Спасибо ВСЕМММММММ!!!
atruhin (2005-08-18 00:20:00) [2]Могу но не буду. Я привел кусок проекта смотри, читай хелп, будут вопросы спрашивай. Там кое что лишнее, элементарного нет, смотри суть.
procedure TAcceptThread.Execute;
не правильная. заметил сейчас, остаток от пула потоков :))
смотри прием, передачу. ДУМАЙ.
Eraser (2005-08-17 23:41:00) [3]NikNet © (17.08.05 23:38) [32]
http://rentacoder.com/
NikNet (2005-08-17 23:38:00) [4]Erik1 © (17.08.05 15:22) [29]
atruhin © (17.08.05 22:59) [31]
Спасибо!!!
Если вас не затруднит :) НЕ могли бы помочь сделать
SendLong то есть передача длиных сообщений и RecvLong
Я думаю это не только решит мою проблему но многих других...
:)
atruhin (2005-08-17 22:59:00) [5]прмерно так
Сервер - но исходник из другого проекта, поэтому смотри анализируй, делай
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 18:14:00) [6]Slym © (17.08.05 04:53) [28]
Можно вопрос? Сколько байт этот код может отправить клиенту/серверу?
Erik1 (2005-08-17 15:22:00) [7]Еще можно глануть исходник Indy там только блокирующий режим используется, поэтому код проще.
Slym (2005-08-17 04:53:00) [8]Выбрось это... Это писал даже не студент первокурсник, а хуже восмикласник.
тоже самое:
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;
NikNet (2005-08-16 18:32:00) [9]А это не моё!!! и я не знаю что-то там вобще...
вот и спрашиваю пример... :=
Digitman (2005-08-16 16:59:00) [10]
> NikNet © (16.08.05 16:55) [25]
прокомментируй каждуюстрочку - что и почему ты делаешь в ней ..
NikNet (2005-08-16 16:55:00) [11]
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 08:24:00) [12]
> передает только 255 байт
приводи свой код
Slym (2005-08-16 04:52:00) [13]У тебя сложности с АПИ? Зачем тебе АПИ?
Все программы используют АПИ ОС! Delphi предлагает удобную "упаковочку" этого АПИ. TServerSocket - АПИ в обектно-ориентированном виде.
kami (2005-08-15 19:14:00) [14]Уппс... не посмотрел, что сервер должен быть на 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 ioresult0 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;
kami (2005-08-15 18:50:00) [15]
> передает только 255 байт
Да вы цё?
Посмотрите ветку http://www.delphimaster.ru/cgi-bin/forum.pl?id=1122136315&n=4
пост [11]
+ если разрешит Verg © - перешлю его пример.
NikNet (2005-08-15 18:16:00) [16]#17
Она передает только 255 байт и все!!! По другому я не умею :(
Digitman (2005-08-15 16:43:00) [17]ты не ответил на вопрос [17]
NikNet (2005-08-15 16:33:00) [18]Ну тогда покажите пример пожалуйста!!! Между
Клиентом и Сервером только что бы Сервер был на API(WinSock)
Прошу вас...
Digitman (2005-08-15 08:49:00) [19]
> NikNet © (15.08.05 03:15) [15]
> SendSock(ConSock,Coompress(’0010Ok’));
надо понимать, процедура SendSock() у тебя данные размером ДО 1Гб передает успешно ? А проблемы возникают лишь при передаче данных размером более чем 1Гб ?
Slym (2005-08-15 04:48:00) [20]NikNet © (14.08.05 18:02) [5]
Этому коду нельзя работать (если он работает)...
Ошибки:
1. break; continue;
2. Работа с неблокирующим сокетом без "сообщений", а опираясь на задержку ЦИКЛОМ!!! и на таймаут.
3. И как ты сЖЫмаешь? 100% ты используешь сжатие без оглядки на фрагментацию пакетов... От этого у тебя "случайные" сбои распаковки