Возникла проблемка при реализации антикапчи... Не знаю в каком типе переменной хранить мусор пикчи . Использую такую фанкшин: Code: function fWSRecv(wHost, wRequest: string):string; var wsData: TWSAData; hHost: PHostEnt; hAddr: TSockAddrIn; hTimeout: TTimeVal; iRead: integer; hData: string; hBuffer: array[0..buffsize] of char; begin WSAStartup($202, wsData); hSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); hHost := gethostbyname(PChar(wHost)); hAddr.sin_family := AF_INET; hAddr.sin_port := htons(80); hAddr.sin_addr := pinaddr(hHost^.h_addr^)^; hTimeout.tv_usec := 0; hTimeout.tv_sec := mstimeout; setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, @hTimeout, sizeof(ttimeval)); connect(hSocket, hAddr, SizeOf(hAddr)); hData := ''; Send(hSocket, wRequest[1], length(wRequest), 0); while (TRUE) do begin FillChar(hBuffer, SizeOf(hBuffer), 0); iRead := Recv(hSocket, hBuffer, length(hBuffer), 0); hData := hData + copy(hBuffer, 0, iRead); if (iRead <= 0) then break; end; CloseSocket(hSocket); WSACleanup; result := hData; end; Она естественно не подходит под пикчи, т.к. возвращает string, а в ней теряется мусор, т.к. он содержит нуль символы. Какой тип данных использовать в result? P.S. Со стрингами я работал через strpos, delete, copy. Нужно чтобы их тоже можно было юзать или укажите аналогичные замены. На antigate.com пример смотрел. IdMultipartFormData - в своей лайт версии delphi не обнаружил. Да и не люблю я инди... Вообще то странно, что нет единой темы про антикапчу. Или я криво смотрел...
как вариант, выделяй память, туда закидывай данные и возвращай указатель на эту память. А там уже как угодно можешь юзать эту память, главное потом не забыть прибить её
Вроде в string нуль символы не должны теряться потому что строка не завершается нуль символом, а перед ней указывается длина. Кроме того в hData будет не только картинка, но и заголовок ответа сервера. А length(hBuffer) случайно не 0? А вообще я выкладывал пример на дельфи для антикапчи /thread151622.html, правда там используется сторонняя dll.
Составил в блокноте... куча ошибок наверное. Боюсь проверять даже на валидность Code: [B]type BArray := array[0..buffsize] of char; var hBuffer: ^BArray; numcap: integer = 1;[/B] function fWSRecv(wHost, wRequest: string):[B]pointer;[/B] var wsData: TWSAData; hHost: PHostEnt; hAddr: TSockAddrIn; hTimeout: TTimeVal; iRead: integer; hData: string; begin WSAStartup($202, wsData); hSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); hHost := gethostbyname(PChar(wHost)); hAddr.sin_family := AF_INET; hAddr.sin_port := htons(80); hAddr.sin_addr := pinaddr(hHost^.h_addr^)^; hTimeout.tv_usec := 0; hTimeout.tv_sec := mstimeout; setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, @hTimeout, sizeof(ttimeval)); connect(hSocket, hAddr, SizeOf(hAddr)); hData := ''; Send(hSocket, wRequest[1], length(wRequest), 0); [B]GetMem(hBuffer, numcap * SizeOf(hBuffer)); FillChar(hBuffer, SizeOf(hBuffer), 0);[/B] while (TRUE) do begin iRead := Recv(hSocket, [B]hBuffer[numcap]^[/B], length(hBuffer), 0); [B]ReallocMem(hBuffer, numcap * SizeOf(hBuffer)); inc(numcap);[/B] if (iRead <= 0) then break; end; CloseSocket(hSocket); WSACleanup; result := hBuffer; [B] FreeMem(hBuffer);[/B] end; Похоже на правду? Лучше SizeOf использовать? Пример, кста, полезный... спс.
GlooK, зачем тебе делать на сокетах, если ты задаешь подобные вотпросы, то может воспользоваться Indy? TIdMultiPartFormDataStream - есть обычный TStream, его можно заменить на TMemoryStream и туда запихнуть нужные данные, эффект будет тот же. Ниже приведу код, идея которого как у slesh'a А по теме : 1. Code: WSAStartup($202, wsData); Вызывается только один раз. 2. Code: result := hBuffer; FreeMem(hBuffer); Как думаешь, что будет когда после вызова своей функции обратишься по возвращаемому адресу? 3. Сделать можно вот так : t Code: ype TMemAndSize = reocrd Mem : Pointer; Size : Cardinal; end; function fWSRecv(wHost, wRequest: string):TMemAndSize; var hHost: PHostEnt; hAddr: TSockAddrIn; hTimeout: TTimeVal; iRead : integer; buffer : array[0..2047] of Byte; begin Result.Mem := nil; Result.Size := 0; hSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); hHost := gethostbyname(PChar(wHost)); hAddr.sin_family := AF_INET; hAddr.sin_port := htons(80); hAddr.sin_addr := pinaddr(hHost^.h_addr^)^; hTimeout.tv_usec := 0; hTimeout.tv_sec := mstimeout; setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, @hTimeout, sizeof(ttimeval)); connect(hSocket, hAddr, SizeOf(hAddr)); {тут нужно проверить результат} Send(hSocket, wRequest[1], length(wRequest), 0); {Проверить результат} repeat iRead := Recv(hSocket, buffer[0], 2048); if iRead <= 0 then Break; Inc(Result.Count, iRead); if not Assigned(Result.Mem) then GetMem(Result.Mem, Result.Count) else Begin ReallocMem(Result.Mem, Result.Count); Move(buffer[0], PByte(Pointer(Result.Count))^, iRead); end; until false; CloseSocket(hSocket); end; {Вспомогательная функция} function fWSRecvStr(wHost, wRequest: string):String; Var tmp : TMemAndSize; Begin Result := ''; try tmp := fWSRecv(wHost, wRequest); finally if Assigned(tmp.Mem) then Begin SetLength(Result, tmp.Size); if tmp.Size > 0 then Move(PByte(Result.Mem)^, Result[1], tmp.Size); FreeMem(tmp.Mem); {Заметим, что теперь мы освобождаем то что создала fWSRecv} end; end; end; {код инициализации/финализации модуля} var wsData: TWSAData; initialization WSAStartup($202, wsData); finalization WSACleanup; end. Могут быть ошибки, т.к. писал в браузере. Хочу так же отметить что освобождение памяти должны делать мы, а не автоматом та функция, которая выделила, причем если указатель не равен Null.