FTP uses multiple socket connections, one for commands/responses, and separate connections for each transfer.
The most likely cause of the socket error is an FTP-unaware proxy/router/firewall sitting in between TIdFTP
and the FTP server is closing the command connection after a short period of inactivity. During the Unpack()
(or manual pause), no commands/responses are being transmitted on the command connection, it is sitting idle, and thus is subject to being closed by a timeout on such a proxy/router/firewall.
During a transfer, the command connection is sitting idle, no FTP commands/responses are being transmitted on it (unless you abort the transfer), until the transfer is complete. An FTP-unaware proxy/router/firewall may close the command connection prematurely during this time.
To avoid that, TIdFTP
has a NATKeepAlive
property that can enable TCP keep-alives on the command connection while it is sitting idle. This usually prevents premature closes.
However, when there is no transfer in prgress, TIdFTP
disables TCP keep-alives on the command connection if NATKeepAlive.UseKeepAlive
is True. TIdFTP
uses TCP keep-alives only during transfers, with the assumption that you are not going to perform long delays in between FTP commands. If you need to delay for awhile, either close the FTP connection, or send an FTP command at regular intervals (such as calling TIdFTP.Noop()
in a timer/thread).
Alternatively, you can try manually enabling TCP keep-alives after connecting to the server, and set NATKeepAlive.UseKeepAlive
to False so TIdFTP
will not automatically disable the keep-alives after each transfer, eg:
function Connect2FTP(FTP: TIdFTP; RemoteFolder: string; Log: TRichLog): Boolean;
begin
Result := FTP.Connected;
if not Result then
begin { We are not already connected }
FTP.Host := MyFTP;
FTP.Username:= usr;
FTP.Password:= psw;
try
FTP.Connect;
try
FTP.ChangeDir(RemoteFolder);
// send a TCP keep-alive every 5 seconds after being idle for 10 seconds
FTP.NATKeepAlive.UseKeepAlive := False; // False by default, but just in case...
FTP.Socket.Binding.SetKeepAliveValues(True, 10000, 5000);
except
FTP.Disconnect(False);
raise;
end;
except
Exit;
end;
Result := True;
end;
end;
Note that while most platforms support enabling TCP keep-alives on a per-connection basis (keep-alives are part of the TCP spec), setting keep-alive intervals is platform-specific. At this time, Indy supports setting the intervals on:
- Windows 2000+ and WinCE 4.x+, for Win32 and .NET
- Linux, when Indy is used in Kylix
- Unix/Linux and NetBSD, when Indy is used in FreePascal.
Otherwise, OS default intervals get used, which may or may not be too large in value for this situation, depending on OS configuration.
At this time, the intervals are not customizable in Delphi FireMonkey, except for Windows.
If a particular platform supports setting custom TCP keep-alive intervals, but Indy does not implement them in SetKeepAliveValues()
, you can use TIdFTP.Socket.Binding.SetSockOpt()
instead to set the values manually as needed. Many platforms do support TCP_KEEPIDLE
/TCP_KEEPINTVL
or equivalent socket options.
Socket error 10038 socket operation on non socket delphi
Профиль
Группа: Участник
Сообщений: 12
Регистрация: 8.4.2006
Репутация: нет
Всего: нет
Вообщем обстоятельства и желания заставили меня учить работу с сокетами, почитав немого книжечку про создания сетевых приложения в Линуксе и порывшись в гугле и MSDN, я написал вот такое вот чудо:
L0n3R4ng3r |
|
||
Код |
/*—————Simple tcp echo server————————*/ |
#include «stdafx.h»
#include «Winsock2.h»
#include «Windows.h»
#include «Winbase.h»
#include «stdio.h»
#include «WINSOCK.H»
#include «string.h»
#pragma comment(lib, «ws2_32.lib»)
int main()
<
int sd;
int bindw;
sockaddr_in addr_in;
sockaddr asd;
ZeroMemory(&asd, sizeof(asd));
char buff[1024];
if (WSAStartup(0x202,(WSADATA *)&buff[0]))
<
printf(«WSAStart error %dn»,WSAGetLastError());
return -1;
>
if (sd=socket(AF_INET, SOCK_STREAM , 0)>=0)
printf(«%sn», «the socket is successfull create»);
else
<
printf(«Error bind %dn»,WSAGetLastError());
closesocket(sd);
WSACleanup();
return -1;
>
ZeroMemory(&addr_in, sizeof(addr_in));
addr_in.sin_family=AF_INET;
addr_in.sin_addr.S_un.S_addr = htons(INADDR_LOOPBACK) ;
addr_in.sin_port=htons(8025);//argv[2];
if (bindw=bind(sd, (struct sockaddr *) &addr_in, sizeof(addr_in)))
<
printf(«Error bind %dn»,WSAGetLastError());
closesocket(sd);
WSACleanup();
return -1;
>
if (listen(sd, 20))
<
printf(«Error bind %dn»,WSAGetLastError());
closesocket(sd);
WSACleanup();
>
printf(«waiting connection. n»);
for (;;)
<
int socksd;
int size=sizeof(addr_in);
socksd = accept(sd, (struct sockaddr*) &addr_in, &size);
if (socksd>0)
<
char buffer[1024];
int nbytes;
do
<
nbytes=recv(socksd,buffer,sizeof(buffer),0);
if (nbytes>0)
send(socksd, buffer, sizeof(buffer), 0);
>
while(nbytes>0 && strncmp(«byer», buffer, 4)!=0);
closesocket(socksd);
>
printf(«Error bind %dn»,WSAGetLastError());
closesocket(sd);
WSACleanup();
exit(1);
>
closesocket(sd);
WSACleanup();
return 0;
>
/*—————————————-End of Source——————————————*/
когда запучтил он мне выдало ошибку 10038, поюзал гугл нашел описание ошибки:
Berkeley description: An operation was attempted on something that is not a socket. The specified socket parameter refers to a file, not a socket.
WinSock description: Same as Berkeley. The socket input parameter is not a valid socket handle (either it never was valid, it’s a file handle (not a socket handle), or if it was a socket handle, it has been closed).
select(): fails with WSAENOTSOCK if any socket in an fd_set is an invalid socket handle.
Developer suggestions: Did you close a socket inadvertently in one part of an application without keeping another part notified? Use socket state in an application and/or handle this error gracefully as a non-fatal error.
WinSock functions: Any function that takes a socket as an input parameter: accept(), bind(), closesocket(), connect(), getpeername(), getsockname(), getsockopt(), ioctl socket(), listen(), recv(), recvfrom(), select(), send(), sendto(), setsockopt(), shutdown(), FD_CONNECT
Additional functions: WSAAsyncSelect() should be in the list of functions (some applications might not register for or handle the FD_CONNECT message).
/*——————————————конец——————————————-*/
Короче сам я разобраться не смог
Г.Ы. Буду благодарен за любую указаную помощь[code=cpp]
Это сообщение отредактировал(а) L0n3R4ng3r — 8.4.2006, 20:40
Профиль
Группа: Участник
Сообщений: 42
Регистрация: 6.4.2006
Репутация: 2
Всего: 2
Ваша ошибка уважаемый в невнимательности и неправильном применении операции присваивания!
Рассмотрите хорошо строку
if (sd=socket(AF_INET, SOCK_STREAM , 0)>=0)
Как Вы думаете — что произойдёт в случае успешного завершения
socket? Вы полагаете что sd получит дескриптор сокета?
А как же приоритет? Ведь у булевых операций он выше — нежели у
оператора =. Вот Вам и ответ — sd всегда будет равен 1. т.к. при
конвертировании true — есть 1! А 1 в linux — это дескриптор вывода cin
если не ошибаюсь. В таких случаях в gcc чтобы страховаться от таких вещей
необходимо использовать опцию -pedantic или просто всегда стараться писать так
if ((sd=socket(AF_INET, SOCK_STREAM , 0))>=0).
040375 |
|
||
|
Профиль
Группа: Участник
Сообщений: 12
Регистрация: 8.4.2006
Репутация: нет
Всего: нет
L0n3R4ng3r |
|
||
Цитата |
почитав немого книжечку про создания сетевых приложения в Линуксе |
забыл дописать что программирую я в среде Windows на Visual C++6.0
. это так лирическое отступления.
исправил действительно sd было равно 1, сейчас ==1956, но существенно ничего не поменялось, ошибка таже самая что и была
Это сообщение отредактировал(а) L0n3R4ng3r — 9.4.2006, 23:45
Профиль
Группа: Участник
Сообщений: 42
Регистрация: 6.4.2006
Репутация: 2
Всего: 2
Я понял по коду — что вы работаете в студио. После некоторых исправлений я скомпилировал в Visual C++ и успешно запустил Ваш код — ошибок там почти нет. Программа работает.
Не помню точно — что правил. Написать подробнее смогу часов через 10 к сожалению
040375 |
|
||
|
Профиль
Группа: Участник
Сообщений: 42
Регистрация: 6.4.2006
Репутация: 2
Всего: 2
Я не смог Вам сразу указать ошибку ещё одну — по той простой причине, что ввёл несколько
изменений сразу в Ваш код. В первую очередь конечно необходимо обращать внимаение на warning-и, которые говорят об изменеии или сокращении типов. Вот строки — которые я изменил в Вашем коде:
struct sockaddr_in addr_in_;
struct sockaddr asd;
— можно конечно и так как Вы написали — но в целях переносимости кода принято писать так.
А вот строка — из-за которой неверно задавался адрес сокета:
addr_in_.sin_addr.S_un.S_addr = htons(INADDR_LOOPBACK) ;
Заменил её на:
addr_in_.sin_addr.s_addr=inet_addr(«127.0.0.1»);
и всё заработало 🙂
040375 |
|
||
|
Профиль
Группа: Участник
Сообщений: 12
Регистрация: 8.4.2006
Репутация: нет
Всего: нет
L0n3R4ng3r |
|
||
Код |
/*—————Simple tcp echo server————————*/ #include «stdafx.h» #include «Winsock2.h» #include «Windows.h» #include «Winbase.h» #include «stdio.h» #include «WINSOCK.H» #include «string.h» #pragma comment(lib, «ws2_32.lib») int main() < int sd; int bindw; struct sockaddr_in addr_in_; struct sockaddr asd; ZeroMemory(&asd, sizeof(asd)); char buff[1024]; if (WSAStartup(0x202,(WSADATA *)&buff[0])) < printf(«WSAStart error %dn»,WSAGetLastError()); return -1; > if (sd=socket(AF_INET, SOCK_STREAM , 0)>=0) printf(«%sn», «the socket is successfull create»); else < printf(«Error bind %dn»,WSAGetLastError()); closesocket(sd); WSACleanup(); return -1; > ZeroMemory(&addr_in_, sizeof(addr_in_)); addr_in_.sin_family=AF_INET; addr_in_.sin_addr.s_addr=inet_addr(«127.0.0.1»); addr_in_.sin_port=htons(8025);//argv[2]; if (bindw=bind(sd, (struct sockaddr *) &addr_in_, sizeof(addr_in_))) < printf(«Error bind %dn»,WSAGetLastError()); closesocket(sd); WSACleanup(); return -1; > if (listen(sd, 20)) < printf(«Error bind %dn»,WSAGetLastError()); closesocket(sd); WSACleanup(); > printf(«waiting connection. n»); for (;;) < int socksd; int size=sizeof(addr_in_); socksd = accept(sd, (struct sockaddr*) &addr_in_, &size); if (socksd>0) < char buffer[1024]; int nbytes; do < nbytes=recv(socksd,buffer,sizeof(buffer),0); if (nbytes>0) send(socksd, buffer, sizeof(buffer), 0); > while(nbytes>0 && strncmp(«byer», buffer, 4)!=0); closesocket(socksd); > printf(«Error bind %dn»,WSAGetLastError()); closesocket(sd); WSACleanup(); exit(1); > closesocket(sd); WSACleanup(); return 0; > /*—————————————-End of Source——————————————*/ |
Профиль
Группа: Участник
Сообщений: 42
Регистрация: 6.4.2006
Репутация: 2
Всего: 2
Привожу весь Ваш код. Не касаясь тонкостесь и приёмов разработки сетевых приложений всё работает.
У меня запускается и ожидает соединения.
Возможно Вам просто нужно сделать rebild
Тот код, где инициализируется winsock в вашем варианте тоже верен,
порсто для меня так привычней.
040375 |
|
||
Код |
#include «Winsock2.h» #include «Windows.h» #include «stdio.h» #include «string.h» #pragma comment(lib, «ws2_32.lib») |
int main()
<
int sd;
int bindw;
struct sockaddr_in addr_in;
struct sockaddr asd;
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 0 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) <
return -1;
>
ZeroMemory(&asd, sizeof(asd));
char buff[1024];
if ((sd=socket(AF_INET, SOCK_STREAM , 0))>0)
printf(«%d%sn», sd, «the socket is successfull create»);
else
<
printf(«Error bind %dn»,WSAGetLastError());
closesocket(sd);
WSACleanup();
return -2;
>
ZeroMemory(&addr_in, sizeof(addr_in));
addr_in.sin_family=AF_INET;
addr_in.sin_port=htons(8025);//argv[2];
addr_in.sin_addr.s_addr=inet_addr(«127.0.0.1»);
if (bind(sd, (struct sockaddr *) &addr_in, sizeof(addr_in)))
<
printf(«Error bind %dn»,WSAGetLastError());
closesocket(sd);
WSACleanup();
return -3;
>
if (listen(sd, 20))
<
printf(«Error bind %dn»,WSAGetLastError());
closesocket(sd);
WSACleanup();
>
printf(«waiting connection. n»);
for (;;)
<
int socksd;
int size=sizeof(addr_in);
socksd = accept(sd, (struct sockaddr*) &addr_in, &size);
if (socksd>0)
<
char buffer[1024];
int nbytes;
do
<
nbytes=recv(socksd,buffer,sizeof(buffer),0);
if (nbytes>0)
send(socksd, buffer, sizeof(buffer), 0);
>
while(nbytes>0 && strncmp(«byer», buffer, 4)!=0);
closesocket(socksd);
>
printf(«Error bind %dn»,WSAGetLastError());
closesocket(sd);
WSACleanup();
exit(1);
>
closesocket(sd);
WSACleanup();
return 0;
>
Профиль
Группа: Участник
Сообщений: 12
Регистрация: 8.4.2006
Репутация: нет
Всего: нет
L0n3R4ng3r |
|
||
Код |
// tcpclient.cpp : Defines the entry point for the console application. // |
#include «stdafx.h»
#include «winsock2.h»
#include «stdio.h»
#include «windows.h»
#include «string.h»
#include «stdlib.h»
#pragma comment(lib, «ws2_32.lib»)
int main()//int argc, char* argv[])
<
sockaddr_in* sock_in_=new sockaddr_in;
SOCKET sd;
int port=80;
char buff[1024];
char ip[20];
ZeroMemory(&ip, sizeof(ip));
ZeroMemory(sock_in_, sizeof(sock_in_));
strcpy(ip,»172.16.0.2″);
if ((sd=socket(AF_INET, SOCK_STREAM,0)) sin_family=AF_INET;
sock_in_->sin_port=htons(port);
if (inet_addr(ip)!=INADDR_NONE)
sock_in_->sin_addr.s_addr=inet_addr(ip);
else
<
printf(«Invalid address %sn»,ip);
closesocket(sd);
free(sock_in_);
WSACleanup();
return -1;
>
int con=0;
if ((con=connect(sd, (sockaddr *)sock_in_, sizeof(sock_in_)))!=0)
<
printf(«Connect error %dn»,WSAGetLastError());
free(sock_in_);
return -1;
>
printf(«%sn%s», «The connetion successfull set», ip);
ZeroMemory(&buff, sizeof(buff));
int nsize;
while((nsize=recv(sd,&buff[0],sizeof(buff)-1,0))!=SOCKET_ERROR)
<
buff[nsize]=0;
printf(«S=>C:%s»,buff);
printf(«S
Код |
/*—————Simple tcp echo server————————*/ #include «stdafx.h» #include «Winsock2.h» #include «Windows.h» #include «Winbase.h» #include «stdio.h» #include «WINSOCK.H» #include «string.h» #pragma comment(lib, «ws2_32.lib») int main() < int sd; int bindw; struct sockaddr_in addr_in_; struct sockaddr asd; ZeroMemory(&asd, sizeof(asd)); char buff[1024]; if (WSAStartup(0x202,(WSADATA *)&buff[0])) < printf(«WSAStart error %dn»,WSAGetLastError()); return -1; > if (sd=socket(AF_INET, SOCK_STREAM , 0)>=0) printf(«%sn», «the socket is successfull create»); else < printf(«Error bind %dn»,WSAGetLastError()); closesocket(sd); WSACleanup(); return -1; > ZeroMemory(&addr_in_, sizeof(addr_in_)); addr_in_.sin_family=AF_INET; addr_in_.sin_addr.s_addr=inet_addr(«172.16.3.10»); addr_in_.sin_port=htons(8025);//argv[2]; if (bindw=bind(sd, (struct sockaddr *) &addr_in_, sizeof(addr_in_))) < printf(«Error bind %dn»,WSAGetLastError()); closesocket(sd); WSACleanup(); return -1; > if (listen(sd, 20)) < printf(«Error bind %dn»,WSAGetLastError()); closesocket(sd); WSACleanup(); > printf(«waiting connection. n»); for (;;) < int socksd; int size=sizeof(addr_in_); socksd = accept(sd, (struct sockaddr*) &addr_in_, &size); if (socksd>0) < char buffer[1024]; int nbytes; do < nbytes=recv(socksd,buffer,sizeof(buffer),0); if (nbytes>0) send(socksd, buffer, sizeof(buffer), 0); > while(nbytes>0 && strncmp(«byer», buffer, 4)!=0); closesocket(socksd); > printf(«Error bind %dn»,WSAGetLastError()); closesocket(sd); WSACleanup(); exit(1); > closesocket(sd); WSACleanup(); return 0; > /*—————————————-End of Source——————————————*/ |
все компилируеться, когда запускаю клиента выдает
Connect error 10014
описание ошибки:
WSAEFAULT (10014) Bad address.
Berkeley description: The system detected an invalid address in attempting to use an argument of a call.
WinSock description: Same as Berkeley, and then some. Specifically, v1.1 WinSock spec notes that this error occurs if the length of the buffer is too small. For instance, if the length of a struct sockaddr is not equivalent to the sizeof(struct sockaddr). However, it also occurs when an application passes an invalid pointer value.
Developer suggestions: Always check the return value from a memory allocation to be sure it succeeded. Always be sure to allocate enough space.
WinSock functions: accept(), bind(), connect(), gethostname(), getpeername(), getsockname(), getsockopt(), recvfrom(), send(), sendto(), setsockopt() if buffer length is too small.
Additional functions: Any functions that takes a pointer as an input parameter: inet_addr(), inet_ntoa(), ioctlsocket(), gethostbyaddr(), gethostbyname(), getservbyname(), getservbyport(), WSAAsyncGetHostByName(), WSAAsyncGetHostByAddr(), WSAAsyncGetProtoByName(), WSAAsyncGetProtoByNumber, WSAAsyncGetServByName(), WSAAsyncGetServByPort(), WSASetBlockingHook()
когда пускаю сервер
error bind 10038
я ее описал в 1-м посте
Компилировал программу на двох компах- итог один
Загнал исходник который мне любезно предоставил уважаемый 040375 в VC++ 6.0 при компиляции выдало:
fatal error C1010: unexpected end of file while looking for precompiled header directive
Может я не тот проект создаю, или . может где-то ошибка на елементарном уровне(ДНК не предлагать )
Профиль
Группа: Участник
Сообщений: 42
Регистрация: 6.4.2006
Репутация: 2
Всего: 2
Уважаемый, я вижу только одну проблему в Вашем коде. Прежде, чем садиться писать сетевые клиент-серверные приложения, советую обратить хоть какое то внимание на основы языка C.
Вы делаете ошибки, как впрочем и все мы, но Вы их не замечаете снова и снова.
Я обращу Ваше внимание только на некоторые, остальные найдёте сами.
ZeroMemory(&ip, sizeof(ip)); такое разрешено — но опять же — принято, что название массива
является и указателем на него — ZeroMemory(ip, sizeof(ip))
ZeroMemory(sock_in_, sizeof(sock_in_)); — здесь Вы обнуляете только первые 4 байта зачем-то динамически созданной структуры sockaddr_in
free(sock_in_) — если Вы создаёте структуру динамически с помощью new, то удалять следует с помощью delete, free освобождает память после malloc и т.п. .
Это что касается клиента.
Ну а в своём сервере Вы опять наступили на старые грабли:
(sd=socket(AF_INET, SOCK_STREAM , 0)>=0). no comment
Дальше даже искать не стал.
Теперь что кается моего (Вашего поправленного) кода — как я уже сказал, я его запускал и он работает без ошибок (по крайней мере вышеназванных). Просто Вы скопировали его в редакторе
кода не оставив пустой последнюю строку или что-то в этом роде. Поставив курсор после последнего символа в коде нажмите Enter, чтобы редактор поставил там /n и EOF — такое случается в редакторах — я сам с этим сталкивался. И разберитесь с опциями компилятора.
Ну и наконец — возмите в руки книгу по С
040375 |
|
||
|
Профиль
Группа: Участник
Сообщений: 12
Регистрация: 8.4.2006
Репутация: нет
Всего: нет
L0n3R4ng3r |
|
||
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) |
0 Пользователей: |
« Предыдущая тема | C/C++: Сети | Следующая тема » |
[ Время генерации скрипта: 0.1433 ] [ Использовано запросов: 21 ] [ GZIP включён ]
Источник
|
|
|
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Сокет и ошибка 10038
- Подписаться на тему
- Сообщить другу
- Скачать/распечатать тему
|
|
Full Member Рейтинг (т): 7 |
День добрый. Добавлено 04.09.08, 12:14 |
trainer |
|
Цитата DrMort @ 04.09.08, 11:29 С другой стороны он передаётся в обработчик, так что существовать должен, в дебаге видно даже его настройки. Какое отношение обработчик события в компоненте VCL имеет к системному объекту? Системный объект видимо удален, экземпляр компонента остался. Любые попытки использовать системный объект через компонент будут давать ошибки(если компонент не будет самостоятельно пересоздавать системный объект, а он в данном случае не будет пересоздавать). Эээ… Ты закрываешь сокет в OnClientDisconnect? Сообщение отредактировано: trainer — 04.09.08, 13:17 |
Akme |
|
Указатели какие-нить не перезаписываешь? Что в дисконекте делается? Один поток в программе или нет? |
DrMort |
|
Full Member Рейтинг (т): 7 |
Никаких указателей не перезаписываю. В дисконнекте меняются просто флажки соединений — то есть в массив проставляется что васе пупкину больше ничего отсылать не стоит — мы его потеряли. Программа однопоточная — никаких специальных замутов наподобии CreateThread не делал. Сейчас попробую привести некий кусок кода void __fastcall TForm1::ServerSocket1ClientDisconnect(TObject *Sender, TCustomWinSocket *Socket) { int CurrentLocation=0,counter=0; int NumSym=0,i,o; AnsiString CurrName=»»; for(i=0;i<MaxConnections;i++) //MaxConnections — константа содержащая максимальное число соединений с клиентами { if((Connections[i].Socket==Socket) && (Connections[i].Connected==true)) { if(Connections[i].Login!=»») { Memo1->Lines->Add(Connections[i].Login+» disconnected»); CurrName=Connections[i].Login; CurrName=CurrName.Trim(); } else Memo1->Lines->Add(«Non logined client disconnected»); Connections[i].Connected=false; Connections[i].Autorize=false; for(o=0;o<BufferLength;o++) Connections[i].SendBuffer[o]=»»; Connections[i].BufferCounter=0; Connections[i].Idle=0; Form1->StatisticMonitor->Values[«CurrentConnection»]=IntToStr(StrToInt(Form1->StatisticMonitor->Values[«CurrentConnection»])-1); break; }; }; } Connections[] — массив структур содержащий сведения о соединениях, В нём есть поле Socket значение которого заполняется при установке связи. Но все это описание зряшное, потомучто содержимое обработчика можно полностью убрать и ничего не изменится — проверено. Так же пробовал в начале каждой процедуры имеющейся в проекте ставить стоп поинт и отслеживать что ещё происходит в момент когда клиент обрывает связь. Так вот ничего не происходит — сразу срабатывает OnClientDisconnect. Сразу после его срабатывания вылетает подряд две ошибки. Так что вероятнее всего дело не в исходном коде, а в настройках/багах проекта/операционной системы/среды программирования. Чуть позже попробую на чистом компе возвести SQL сервер и запустить серверное приложение. Если ошибка исчезнет — всему виной срада/операционка. |
leo |
|
Цитата DrMort @ 05.09.08, 01:20 В дисконнекте меняются просто флажки соединений — то есть в массив проставляется что васе пупкину больше ничего отсылать не стоит — мы его потеряли
И что разорванное соединение так и остается навсегда в массиве Connections или удаляется ? Цитата DrMort @ 05.09.08, 01:20 Программа однопоточная — никаких специальных замутов наподобии CreateThread не делал
Чтобы прога стало многопоточной достаточно установить «замут» ServerType:=stThreadBlocking |
DrMort |
|
Full Member Рейтинг (т): 7 |
Разорваное соединение остаётся, но никогда не используется. По прошествии некоторого времени по таймеру выбираются все разорваные соединения и удаляются из массива. |
Oleg2004 |
|
Есть такая ситуация — что в режиме дебага многие среды при тестирование клиент-серверных приложений глючат. |
DrMort |
|
Full Member Рейтинг (т): 7 |
Вне среды все равно глючит. Переставил винду — все та же ошибка. Завтра попробую переставить винду и не ставить ни одного драйвера. |
DrMort |
|
Full Member Рейтинг (т): 7 |
Переставил винду поверх старой. Глючит. Форматнул винт — нормально. С дровами тоже нормально. Похоже что-то было с операционкой, может какие нить последствия лечения вирусни. Всем спасибо за мысли. |
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- Borland C++ Builder/Turbo C++ Explorer
- Следующая тема
[ Script execution time: 0,0314 ] [ 16 queries used ] [ Generated: 10.02.23, 02:42 GMT ]
0 / 0 / 0 Регистрация: 30.10.2018 Сообщений: 21 |
|
1 |
|
29.06.2020, 15:20. Показов 3416. Ответов 2
Написал простенькую программу для проверки почты с использованием компонентов Indy. При попытке получить почту
__________________
0 |
пофигист широкого профиля 4602 / 3062 / 850 Регистрация: 15.07.2013 Сообщений: 17,661 |
|
30.06.2020, 03:57 |
2 |
10038 (WSAENOTSOCK): Socket operation on nonsocket. An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid.
0 |
0 / 0 / 0 Регистрация: 30.10.2018 Сообщений: 21 |
|
04.07.2020, 13:38 [ТС] |
3 |
Вот архив с проектом: Hedwig.rar
0 |
← →
Pcrepair ©
(2012-12-27 11:20)
[0]
Добрый день.
Есть функция вида function LoadPage(const Url:string):string; для закачки страниц на базе idHHP.Get, которая обеспечивает:
— закачку страниц с фреймами
— закачку страниц по HTTPs
— смену Request.UserAgent (доп. функция) по Random из списка агентов
— подавление исключений в коде idHHP.Get с записью в лог причин
— вывод сообщений о утечке памяти при закрытии Арр
Сама по себе функция работает нормально, загружает все страницы и без утечки памяти.
Есть код запуска этой функции в многопоточном режиме:
unit Main;
....
implementation
{$R *.dfm}
uses uLoadPage,uGlobalVar;
(*нажимает эту кнопку и понеслось*)
procedure TMainForm.Btn_StartLoadURLsClick(Sender: TObject);
var
UrlList:TStringList; (*эквивалент передаваемого массива строк из ПМ*)
i:integer;
Url:string; (*строка = УРЛ из массива*)
begin
UrlList:=TStringList.Create;
UrlList.Text:=Mm_InsSMUrls.Text; (*ввод массива строк УРЛ*)
(*----ЦИКЛ мульти закачки страниц по числу УРЛ в Mm_InsSMUrls---*)
for i := 0 to UrlList.Count-1 do
begin
Url:=UrlList[i]; (*передача УРЛ*)
Loader(Url); (*вызов процедуры запуска потока закачки страницы*)
Sleep(10); (*страховка от перегрева процессора а также от толпы потоков, которые мешают друг другу?*)
end;
FreeAndNil(UrlList);
end;
unit uLoadPage;
interface
uses SysUtils, uThreadLoader, Classes;
Procedure Loader(Url:string);
implementation
Procedure Loader(Url:string);
var ThreadLdr: TLoader;
begin
ThreadLdr:=Tloader.Create(True);
ThreadLdr.Priority:=tpNormal;
ThreadLdr.FreeOnTerminate:=True;
ThreadLdr.Url:=Url;
ThreadLdr.Start;
end;
end.
unit uThreadLoader;
interface
uses
System.Classes, idHTTP, SysUtils, Dialogs;
type
TLoader = class(TThread)
private
FUrl:string;
FHtml:string;
{ Private declarations }
protected
procedure Execute; override;
procedure CallStore;
function LoadHtmlCode(const Url:string):string;
public
property Url: string read FUrl write FUrl; (*свойство класа, доступное для всей программы*)
property Html: string read FHtml write FHtml;
end;
implementation
uses uPageLoader, uLoadPage, uGlobalVar;
function TLoader.LoadHtmlCode(const Url:string):string;
begin
Result:=LoadPage(Url); (*вызываем функцию загрузки страницы из uPageLoader*)
end;
procedure TLoader.CallStore;
begin
gStore.Add(Html); (*ввод новой строки в ГлобПерем*)
end;
procedure TLoader.Execute;
begin
Html:=LoadHtmlCode(Url); (*загрузка страницы в Поле Класса(свойство)*)
CS.Enter; (*вход в КС*)
CallStore; (*передаем результат в ГП*)
Cs.Leave; (*выход из КС*)
end;
end.
unit uPageLoader;
interface
uses Classes, SysUtils, idHTTP, StrUtils, IdSSL, IdSSLOpenSSL;
function LoadPage(const Url:string):string; (*Основная функция Юнита*)
procedure ErrorLog(Url:string);
function LoadHtmlPage(const PageUrl:string):string;
function DelJS(const Code:string):string;
function RestoreFrame(const Code:string):string;
function RestoreFullUrl(const Code:string; const RootUrl:string):string;
function GetRandomUserAgent: string;
var
Loader:TidHTTP;
SSL:TIdSSLIOHandlerSocketOpenSSL;
implementation
тут много чего, но все работает, смотри в начало
end.
unit uGlobalVar;
interface
uses Classes, SysUtils, SyncObjs;
var
gStore: TStringList=nil; (*ГП для хранения закачанных страниц*)
CS:TCriticalSection; (*используем КС для передачи результата в основной поток*)
implementation
initialization
gStore:=TStringList.Create;
gStore.Duplicates:=dupAccept;
gStore.Sorted:=False;
Cs:=TCriticalSection.Create;
finalization
FreeAndNil(gStore);
FreeAndNil(CS);
end.
Результат:
В режиме отладки видно что возникает множество самых различных ошибок:
— First chance exception at $00407466. Exception class $C0000005 with message «access violation at 0x00407466: read of address 0x000000a4». Process Loader_VER06.exe (2012)
— First chance exception at $7C812AFB. Exception class EIdHTTPProtocolException with message «Set-Cookie: dle_password=deleted; expires=Tue, 27-Dec-2011 20:37:50 GMT; path=/; domain=.freeseller.ru; httponly». Process Loader_VER06.exe (2012)
First chance exception at $00629F8C. Exception class $C0000005 with message «access violation at 0x00629f8c: read of address 0x00000148». Process Loader_VER06.exe (2012)
— First chance exception at $7C812AFB. Exception class EOSError with message
«System Error. Code: 123. Синтаксическая ошибка в имени файла, имени папки или метке тома».
Process Loader_VER06.exe (2012)
— First chance exception at $7C812AFB. Exception class EIdNotASocket with message
«Socket Error # 10038
Socket operation on non-socket.».
Process Loader_VER06.exe (2012)
В рабочем режиме, за счет подавления исключений, все это конечно не вылазит, но:
— закачиваются не все страницы(хотя все УРЛ валидные и функцией закачки закачиваются без вопросов)
— после закрытия Арр выводится сообщение о многочисленных маленьких утечках памяти
По теории потоки не должны пересекаться. каждый имеет свою память. вывод результата через КС. такое впечетление что потоки как то мешают друг другу
Внимание!!! Вопрос: в чем может быть причина появления исключений и утечки памяти именно в режиме многопотоковой закачки?
← →
brother ©
(2012-12-27 11:45)
[1]
> исключений и утечки памяти
исключения дают утечки…
← →
Сергей М. ©
(2012-12-27 11:51)
[2]
В упор не видно защиты глоб.ресурса gStore критической секцией.
Ты объект Cs вообще зачем создавал, не для этого ли как раз ?
← →
Игорь Шевченко ©
(2012-12-27 11:51)
[3]
> Вопрос: в чем может быть причина появления исключений и
> утечки памяти именно в режиме многопотоковой закачки?
Наверное в режиме отладки и строки, на которых проиходит исключение, показываются.
Не томи.
← →
icWasya ©
(2012-12-27 11:55)
[4]
Ну а в однопоточном режиме всё работает?
Ну то есть вот такProcedure Loader(Url:string);
var ThreadLdr: TLoader;
begin
ThreadLdr:=Tloader.Create(True);
ThreadLdr.Priority:=tpNormal;
ThreadLdr.FreeOnTerminate:=True;
ThreadLdr.Url:=Url;
(*ThreadLdr.Start; вместо этого*)
ThreadLdr.Execute;//<<==-- вот это
ThreadLdr.Free;//<<==--
end;
← →
Сергей М. ©
(2012-12-27 12:32)
[5]
> вывод результата через КС
procedure TLoader.CallStore;
begin
cs.Enter;
try
gStore.Add(Html); // вот теперь ресурс действительно защищен, никакие утечки теперь не грозят
finally
cs.Leave;
end;
end;
← →
Сергей М. ©
(2012-12-27 12:34)
[6]
Разумеется «читающий» поток, тот который «выгребает» все это хозяйство из gStore, точно так же обязан входить в КС при этом.
← →
anonims
(2012-12-27 12:52)
[7]
В одном потоке все работает => LoadPage не потокобезоасна. (использует и меняет не локальные данные).function TLoader.LoadHtmlCode(const Url:string):string;
begin
Result:=LoadPage(Url); (*вызываем функцию загрузки страницы из uPageLoader*)
end;
unit uPageLoader;
interface
uses Classes, SysUtils, idHTTP, StrUtils, IdSSL, IdSSLOpenSSL;
function LoadPage(const Url:string):string; (*Основная функция Юнита*)
var
Loader:TidHTTP;
SSL:TIdSSLIOHandlerSocketOpenSSL;
использование одного Loader, SSL для ВСЕХ потоков.
> тут много чего, но все работает, смотри в начало
тоже все глобальные объекты едины для всех потоков.
← →
Pcrepair ©
(2012-12-27 14:03)
[8]
anonims
> использование одного Loader, SSL для ВСЕХ потоков.
что ты имеешь ввиду? что нужно написать одинаковый код для скажем 10 потоков и для каждого прописать свой idHTTP, типа
idHTTP_1
idHTTP_2 и так далее и для каждого свое создание-уничтожение и все прочее?
++++++++++++++++++++++++++++++
Сергей М.
> Разумеется «читающий» поток, тот который «выгребает» все
> это хозяйство из gStore, точно так же обязан входить в КС
> при этом.
все правильно конечно, но в текущей ситуации(стенд) обращение к накопителю идет вручную только после окончания работы всех потоков(контроль по диспетчеру задач), так что к описанным проблемам это пока не имеет отношения. вместе с тем, кто знает программу более функциональную чем Диспетчер задач, для наблюдения за потоками выбранного приложения?
и еще вопрос: там перем Html прописана как свойство класса, хотя можно прописать ее ка переменную в ПАБЛИК. в чем разница? и как правильно
+++++++++++++++++++++++++++++
Игорь Шевченко
там выводит код из модулей ИНДИ
типа
unit IdSSLOpenSSL
procedure TIdSSLIOHandlerSocketOpenSSL.ConnectClient;
var
LPassThrough: Boolean;
begin
(*RLebeau 1/11/07:
In case a proxy is being used, pass through any data from the base class unencrypted when setting up that connection.
///В случае, если используется прокси-сервер, пройти через любые данные из базового класса, незашифрованные при создании связи
We should do this anyway since SSL hasn"t been initialized yet!
///Мы должны сделать это в любом случае, поскольку SSL не была инициализирована
*)
LPassThrough := fPassThrough;
fPassThrough := True;
try
inherited ConnectClient; (*исключение*)
finally
fPassThrough := LPassThrough;
end;
DoBeforeConnect(Self);
// CreateSSLContext(sslmClient);
// CreateSSLContext(SSLOptions.fMode);
StartSSL;
end;
Только в многопоточном режиме исключение?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Socket Error 10056
модуль IdStack
сообщение:
procedure TIdStack.RaiseSocketError(AErr: integer);
begin
(*
RRRRR EEEEEE AAAA DDDDD MM MM EEEEEE !! !! !!
RR RR EE AA AA DD DD MMMM MMMM EE !! !! !!
RRRRR EEEE AAAAAA DD DD MM MMM MM EEEE !! !! !!
RR RR EE AA AA DD DD MM MM EE
RR RR EEEEEE AA AA DDDDD MM MM EEEEEE .. .. ..
Please read the note in the next comment.
*)
if AErr = Id_WSAENOTSOCK then begin
// You can add this to your exception ignore list for easier debugging.
// However please note that sometimes it is a true error. Your program
// will still run correctly, but the debugger will not stop on it if you
// list it in the ignore list. But for most times its fine to put it in
// the ignore list, it only affects your debugging.
raise EIdNotASocket.CreateError(AErr, WSTranslateSocketErrorMsg(AErr));
end;
(*
It is normal to receive a 10038 exception (10038, NOT others!) here when
*shutting down* (NOT at other times!) servers (NOT clients!).
If you receive a 10038 exception here please see the FAQ at:
http://www.IndyProject.org/
If you insist upon requesting help via our email boxes on the 10038 error
that is already answered in the FAQ and you are simply too slothful to
search for your answer and ask your question in the public forums you may be
publicly flogged, tarred and feathered and your name may be added to every
chain letter / EMail in existence today."
Otherwise, if you DID read the FAQ and have further questions, please feel
free to ask using one of the methods (Carefullly note that these methods do
not list email) listed on the Tech Support link at:
http://www.IndyProject.org/
RRRRR EEEEEE AAAA DDDDD MM MM EEEEEE !! !! !!
RR RR EE AA AA DD DD MMMM MMMM EE !! !! !!
RRRRR EEEE AAAAAA DD DD MM MMM MM EEEE !! !! !!
RR RR EE AA AA DD DD MM MM EE
RR RR EEEEEE AA AA DDDDD MM MM EEEEEE .. .. ..
*)
raise EIdSocketError.CreateError(AErr, WSTranslateSocketErrorMsg(AErr));
end;
а вот что это значит и что с этим делать?
← →
Сергей М. ©
(2012-12-27 14:16)
[9]
> к описанным проблемам это пока не имеет отношения
«пока» может и не имеет, тебе виднее.
А потом поимеет — попросту забудешь про синхронизацию, как сейчас «забыл» про нее в CallStore.
Лучше таки сразу предусмотреть синхронизацию для всех потенциально возможных случаев. И обратить при этом внимание на TMultiReadExclusiveWriteSynchronizer как возможно более разумную альтернативу TCriticalSection.
← →
RWolf ©
(2012-12-27 14:31)
[10]
> что нужно написать одинаковый код для скажем 10 потоков
> и для каждого прописать свой idHTTP, типаidHTTP_1idHTTP_2
> и так далее и для каждого свое создание-уничтожение и все
> прочее?
ну, а как думаешь, данные глобального объекта idHTTP каким-то волшебным образом избегут разрушения, когда их модифицируют несколько потоков?
для каждого свой, конечно.
← →
Сергей М. ©
(2012-12-27 14:42)
[11]
> перем Html прописана как свойство класса, хотя можно прописать
> ее ка переменную в ПАБЛИК. в чем разница? и как правильно
А зачем она вообще нужна именно в описании класса ? Кто к ней обращается кроме членов самого класса TLoader ?
Судя по приведенному коду это вообще переменная временного назначения, место которой — в стеке, т.е. среди локальных переменных подпрограмм.
← →
Pcrepair ©
(2012-12-27 14:59)
[12]
> А зачем она вообще нужна именно в описании класса ? Кто
> к ней обращается кроме членов самого класса TLoader ?
это рудимент предыдущих экспериментов
получается нужно писать код нескольких потоков, имеющих каждый свой idHTTP.Get и весь код обработки страницы, а не вызывать функции из доп. модулей? чтоб гарантированно не было исключений?
может тогда уже свой класс правильней написать? с использованием внутри этого класса потоков.
создавать потомок класса, передавать ему значение(УРЛ) + написать класс НАКОПИТЕЛЬ в который передавать асинхронно результат работы
с ООП знаком пока только теоритически
← →
bems ©
(2012-12-27 15:04)
[13]
вызывать функции других модулей можно, но нельзя при этом обращаться к общим данным без синхронизации.
например можно сделать функции LoadPage еще один параметр типа TidHttp и передавать в него экземпляр, с которым работает только вызывающий поток
← →
Сергей М. ©
(2012-12-27 15:44)
[14]
> а не вызывать функции из доп. модулей?
Вопрос о выносе частей кода в отдельные юниты — это не более чем вопрос об удобстве восприятия текста проекта, ну и еще вопрос использования общих фрагментов кода со стороны других модулей.
← →
Pcrepair ©
(2012-12-27 17:26)
[15]
> bems © (27.12.12 15:04) [13]
> вызывать функции других модулей можно, но нельзя при этом
> обращаться к общим данным без синхронизации.
> например можно сделать функции LoadPage еще один параметр
> типа TidHttp и передавать в него экземпляр, с которым работает
> только вызывающий поток
это типа
function TForm1.LoadPage(const S:string; idHttp: TidHttp):string;
begin
idHttpLoad := TIdHTTP.Create(nil);
try
LoadPage := (AnsiLowerCase(idHttpLoad.Get(S)));
finally
idHttpLoad.Free;
end;
end;
← →
bems ©
(2012-12-27 18:56)
[16]
типа function LoadPage(const Url: String; IdHttp: TIdHttp): String;
begin
Result := AnsiLowerCase(IdHttp.Get(Url))
end;
function TLoader.LoadHtmlCode(const Url: String): String;
begin
Result:=LoadPage(Url, FIdHttp)
end;
, где FIdHttp — поле TLoader, присваиваемое в конструкторе
← →
Pcrepair ©
(2012-12-27 20:07)
[17]
что то такую форму записи Result:=LoadPage(Url, FIdHttp) нигде в букварях не встречал
FIdHttp — это в
TLoader = class(TThread)
private
FIdHttp:TidHTTP;
объявить?
← →
bems ©
(2012-12-27 20:30)
[18]
объявить. и в конструкторе присвоить FIdHttp := TIdHTTP.Create(nil);
в деструкторе соответственно освободить
что именно не встречал?
← →
Pcrepair ©
(2012-12-27 21:31)
[19]
вот это: (Url, FIdHttp)
но не будем отвлекаться на пустяки, итого нужно следующее
type
TLoader = class(TThread)
private
FUrl:string;
FIdHttp:TidHTTP;
protected
procedure Execute; override;
function TLoader.LoadHtmlCode(const Url: String): String;
public
property Url: string read FUrl write FUrl; (*свойство класа, доступное для всей программы*)
constructor Create;
destructor Destroy; override;
end;
implementation
uses uPageLoader, uLoadPage, uGlobalVar;
constructor TLoader.Create(FIdHttp := TIdHTTP.Create(nil));
begin
inherited Create(True); (*Поток создаем в состоянии «Приостановлен»*)
FreeOnTerminate := True; (* Поток освободит ресурсы при окончании работы*)
Self.Priority := tpNormal;
end;
destructor TLoader.Destroy;
begin
FreeAndNil(FIdHttp);
end;
function TLoader.LoadHtmlCode(const Url: String): String;
begin
Result:=LoadPage(Url, FIdHttp)
end;
procedure TLoader.Execute;
var Code:string;
begin
Code:=LoadHtmlCode(Url, IdHttp);
CS.Enter; (*вход в КС*)
gStore.Add(Code); (*передаем результат в ГП*)
Cs.Leave; (*выход из КС*)
end;
end.
+++++++++++++++другой модуль++++++++++++++++++++
function LoadPage(const Url: String; IdHttp: TIdHttp): String;
begin
Result := AnsiLowerCase(IdHttp.Get(Url))
end;
а вызов потока останется прежний?
← →
bems ©
(2012-12-27 21:45)
[20]
constructor TLoader.Create(FIdHttp := TIdHTTP.Create(nil));
что это?
в теле конструктора присваивай, там же где FreeOnTerminate := True
← →
bems ©
(2012-12-27 21:49)
[21]
вызов от этого не меняется.
но по хорошему не нужно создавать отдельный поток на каждый урл, а использовать фиксированное (или динамическое, но с ограничением) число тредов, каждый из которых обрабатывает урлы по очереди
← →
Pcrepair ©
(2012-12-27 22:04)
[22]
да, это многие советуют — создать пул потоков и давать им задания по закачке страниц. но это следующий этап. пока нужно с этим вариантом разобраться, в частности замечено что на
SSL:=TIdSSLIOHandlerSocketOpenSSL.Create;
Loader.IOHandler:=SSL;
идут исключения в соответствующем модуле ИНДИ.
видимо надо усложнить:
constructor TLoader.Create;
begin
inherited Create(True); (*Поток создаем в состоянии «Приостановлен»*)
FIdHttp := TIdHTTP.Create(nil);
FSSL := TIdSSLIOHandlerSocketOpenSSL.Create;
FreeOnTerminate := True; (* Поток освободит ресурсы при окончании работы*)
Self.Priority := tpNormal;
end;
что касается вызова, там ведь тоже есть
ThreadLdr:=Tloader.Create(True); (*создаем поток, но не запускаем*)
ThreadLdr.Priority:=tpNormal; (*задать приортет нормальный*)
ThreadLdr.FreeOnTerminate:=True; (*самовыгрузка в конце потока*)
(*передача в поток данных*)
ThreadLdr.Url:=Url; (*передаем УРЛ в Поток*)
(*запуск поток на выполнение*)
ThreadLdr.Start;
получается свой конструктор просто дополняет родительский класс новыми свойствами?
в ООП пока не сильно
← →
bems ©
(2012-12-27 22:13)
[23]
аа, не, после того как ты добавил конструктор без параметров, вызвать Create(True) уже нельзя
создавай просто ThreadLdr := Tloader.Create; а остальное у тебя уже внутри конструктора
← →
Сергей М. ©
(2012-12-27 22:13)
[24]
> в ООП пока не сильно
Вот это безобразие
> Create(FIdHttp := чегототам);
в сущности не имеет отношения к ООП
← →
Pcrepair ©
(2012-12-27 22:22)
[25]
> в сущности не имеет отношения к ООП
ага, разве TThread это не объект? со всеми втекающими и вытекающими
и в чем тут безобразие? поканкратнее пжалуйста
← →
bems ©
(2012-12-27 22:32)
[26]
в том что это не скомпилируется
← →
Сергей М. ©
(2012-12-27 23:00)
[27]
> в чем тут безобразие?
см. [26]
← →
Pcrepair ©
(2012-12-27 23:16)
[28]
не будем спотыкаться об уже пройденное, лучше продолжим:
Сама структура программы в принципе правильная?
— получаем список строк(УРЛ)
— запускаем конвейер потоков, передаем каждому свой УРЛ
— по закачке страницы, поток передает результат в ГлобПерем
— поток самоликвидируется
начинай сначала
получается что в начальный момент может одновременно запуститься практически от 50 до 200 потоков реально
складывается впечетление(по ошибке 10038 и 10056) что где то есть узкое место, всем потокам не хватает трафика и некоторые получают отказ. непонятно только как, временные интервалы в idHTTP для подключения к серверу и работы с сервером установлены в 50 сек.
или есть решения поумнее?
← →
Сергей М. ©
(2012-12-27 23:19)
[29]
> есть решения поумнее?
Объясни накой тебе аж 50 и более потоков ?
← →
bems ©
(2012-12-27 23:31)
[30]
> в начальный момент может одновременно запуститься практически
> от 50 до 200 потоков
если у тебя есть много урлов еще до старта первого потока, то можно сразу отдать каждому треду пачку урлов и пусть обрабатывает их в цикле. это легко, потому что не нужно делать добавление задания на закачку в уже существующий поток
> реально
> складывается впечетление(по ошибке 10038 и 10056) что где
> то есть узкое место, всем потокам не хватает трафика и некоторые
> получают отказ
в варианте без общего использования одного idHttp ошибки остаются?
← →
Pcrepair ©
(2012-12-27 23:31)
[31]
для полного использования трафика. в среднем скорость выдачи у серверов небольшая. если трафик к примеру 5000 кбитсек, при средней скорости отдачи серверов 50 кбитсек можно запускать до 100 потоков одновременно, ну чтоб провыдЫр не за так деньги получал
← →
Pcrepair ©
(2012-12-27 23:36)
[32]
> в варианте без общего использования одного idHttp ошибки
> остаются?
этот вариант еще не попробовал и вот почему: на самом деле функция в 19
+++++++++++++++другой модуль++++++++++++++++++++
function LoadPage(const Url: String; IdHttp: TIdHttp): String;
begin
Result := AnsiLowerCase(IdHttp.Get(Url))
end;
IdHttp не содержит. LoadPage состоит из нескольких функций
unit uPageLoader;
interface
uses Classes, SysUtils, idHTTP, StrUtils, IdSSL, IdSSLOpenSSL;
function LoadPage(const Url:string):string; (*Основная функция Юнита*)
procedure ErrorLog(Url:string);
function LoadHtmlPage(const PageUrl:string):string;
function DelJS(const Code:string):string;
function RestoreFrame(const Code:string):string;
function RestoreFullUrl(const Code:string; const RootUrl:string):string;
function GetRandomUserAgent: string;
var
Loader:TidHTTP;
SSL:TIdSSLIOHandlerSocketOpenSSL;
в том числе function LoadHtmlPage(const PageUrl:string):string; в которой как и есть idHTTP
Пока не совсем понятно как вызывать свой экземпляр idHTTP и SSL
Никаких идей нет?
← →
Сергей М. ©
(2012-12-27 23:43)
[33]
> чтоб провыдЫр не за так деньги получал
О как сурово)
← →
bems ©
(2012-12-27 23:49)
[34]
передавай через параметр как и в LoadPage.
ssl на момент вызова уже по идее должен быть присвоен в iohandler, поэтому ssl вообще можно убрать
← →
Pcrepair ©
(2012-12-28 00:04)
[35]
> ssl на момент вызова уже по идее должен быть присвоен в
> iohandler, поэтому ssl вообще можно убрать
некоторые утверждают что SSL:TIdSSLIOHandlerSocketOpenSSL; тоже получается как и idHTTP общее для всех потоков. и при отладке выскакивают исключения, которые указывают на модуль IdSSLOpenSSL(смотри[8])
в общем прийдется модуль переписать, под многопоточность
← →
Pcrepair ©
(2012-12-28 00:05)
[36]
а может попробовать в качестве загрузчика ICS
← →
bems ©
(2012-12-28 00:11)
[37]
> некоторые утверждают что SSL:TIdSSLIOHandlerSocketOpenSSL;
> тоже получается как и idHTTP общее для всех потоков. и
> при отладке выскакивают исключения, которые указывают на
> модуль IdSSLOpenSSL
общий, но ты ж добавил в конструктор треда FSSL := TIdSSLIOHandlerSocketOpenSSL.Create;
вот остальные ssl убирай, и присваивай FidHttp.IoHandler еще перед вызовом LoadPage
ну и в uPageLoader передавай IdHttp везде через параметр
← →
Германн ©
(2012-12-28 01:44)
[38]
> Pcrepair © (28.12.12 00:05) [36]
>
> а может попробовать в качестве загрузчика ICS
Попытка — не пытка. Попробуй.
Лично я предпочитаю всегда ICS. Но я не занимался разработкой «поисковой машины». Так что мне больше нечего сказать.
← →
Pcrepair ©
(2012-12-28 16:30)
[39]
ну раз ты предпочитаешь ICS, тогда поведай миру о своем опыте, конкретно, есть ли в ICS:
— встроенная обработка перенаправления 301 и 302
— правильная кодировка кирилицы(так называемые кракрзябры вместо правльных букаф)
— возможность закачки HTTPs
— возможность установки нужного значения юзер-агент
— управление временем подключения к серверу и работы с сервером. ограничение в смысле
как видишь, если у тебя есть опыт работы, сказать много что вполне возможно
можно и примерный код выставить, или хотя бы дать ссылки
ждемс
← →
Pcrepair ©
(2012-12-28 19:22)
[40]
а если вот так:
type
TLoader = class(TThread) (*создаем свой класс на базе ПОТОК*)
private
FUrl:string; (*поле класса типа СТРОКА для чтения -записи данных*)
FIdHttp:TidHTTP;
FSSL:TIdSSLIOHandlerSocketOpenSSL;
protected
procedure Execute; override;
function LoadHtmlCode(const Url: String):string; (*ФУНК загрузки страницы*)
public
property Url: string read FUrl write FUrl; (*свойство класа, доступное для всей программы*)
constructor Create;
destructor Destroy; override;
end;
implementation
uses Unit1, uLoadPage, uGlobalVar;
constructor TLoader.Create;
begin
inherited Create(True); (*Поток создаем в состоянии «Приостановлен»*)
FIdHttp := TIdHTTP.Create(nil);
FSSL := TIdSSLIOHandlerSocketOpenSSL.Create;
FreeOnTerminate := True; (* Поток освободит ресурсы при окончании работы*)
Self.Priority := tpNormal;
end;
destructor TLoader.Destroy;
begin
FreeAndNil(FIdHttp);
FreeAndNil(FSSl);
end;
(* 28.12.2012 функция загрузки страницы прямо в коде потока*)
function TLoader.LoadHtmlCode(const Url: String):string;
begin
FIdHttp.IOHandler:=FSSL;
FIdHttp.HandleRedirects:=True;
Result:=FIdHttp.Get(Url);
end;
procedure TLoader.Execute;
var Code:string;
begin
Code:=LoadHtmlCode(Url);
begin
CS.Enter; (*вход в КС*)
try
gStore.Add(Code); (*передаем результат в ГП*)
finally
Cs.Leave; (*выход из КС*)
end;
end;
end;
end.
то есть функция загрузки с idHTTP прямо в потоке. потом тут же дописать обертку (небольшой цикл по закачке фреймов) а функции обработки кода страницы вообще вызывать в поток из другого модуля
или еще лучще тут их написать но не как метод потока а сверху так сказать. или все же лучше сделать все функции методами класса??
This code raised an EIdNotASocket exception.
function PortInUse(const APort:Integer;const Address:string='localhost'):Boolean;
var
LTcpClient : TIdTCPClient;
begin
LTcpClient := TIdTCPClient.Create(nil);
try
try
LTcpClient.Host := Address;
LTcpClient.Port := APort;
LTcpClient.ConnectTimeout := 200;
LTcpClient.Connect;
Result := True;
except
Result := False;
end;
finally
freeAndNil(LTcpClient);
end;
end;
===============================================================================
Application Name : DSFInterface.exe
Memory manager : FastMM
Compiler Version : Delphi: 34
Indy Version : 10.6.2.0
Zeos Version : 7.2.14-release
Report Unique ID : {9E064C95-AA3D-4658-BF59-FFE405865C5C}
Start Time : 2021-08-05 11:45:18.843
Exception Time : 2021-08-05 11:46:20.381
Application up time : 1 minute 1 second 538 milliseconds
===============================================================================
Processor : LENOVO, LNVNB161216, AMD64 Family 21 Model 112 Stepping 0, AMD A4-9125 RADEON R3, 4 COMPUTE CORES 2C+2G , 2.3 GHz
System : Windows 10 (Version 10.0, Build 19043, 64-bit Edition)
Display : 1680x1050 pixels, 96 bpp
Total Physical Memory : 6.608 GB
Free Physical Memory : 2.137 GB
Max used Memory : 201.594 MB
===============================================================================
Exception class : EIdNotASocket
Socket Error # 10038
Socket operation on non-socket.
Exception address : 000000000095CAD1
Exception trigger : ExceptionAcquired
-------------------------------------------------------------------------------
Module : JclDebug
Command Line : D:Applications-FolderDSFInterfaceDSFInterface.exe
Procedure : JclDebug.TJclStackInfoList.Create
Unit : JclDebug.pas
Line : 5509
-------------------------------------------------------------------------------
[00000000009075B1] JclDebug.TJclStackInfoList.Create (Line 5509, "JclDebug.pas" + 34) + $0
[00000000009070D2] JclDebug.JclCreateStackList (Line 5351, "JclDebug.pas" + 1) + $3E
[0000000000906FB4] JclDebug.DoExceptionStackTrace (Line 5292, "JclDebug.pas" + 20) + $1F
[0000000000909E0C] JclDebug.DoExceptNotify (Line 6741, "JclDebug.pas" + 7) + $0
[00000000008F54C2] JclHookExcept.TNotifierItem.DoNotify (Line 272, "JclHookExcept.pas" + 5) + $1D
[00000000008F5793] JclHookExcept.DoExceptNotify (Line 347, "JclHookExcept.pas" + 21) + $2B
[00000000008F5890] JclHookExcept.HookedRaiseException (Line 381, "JclHookExcept.pas" + 14) + $0
[0000000000410EE3] System.@RaiseAtExcept (Line 22019, "System.pas" + 32) + $0
[0000000000410F01] System.@RaiseExcept (Line 22108, "System.pas" + 2) + $0
[000000000095CAD1] IdStack.TIdStack.RaiseSocketError (Line 976, "IdStack.pas" + 54) + $0
[000000000095CA61] IdStack.TIdStack.RaiseLastSocketError (Line 900, "IdStack.pas" + 2) + $0
[000000000095C98E] IdStack.TIdStack.CheckForSocketError (Line 875, "IdStack.pas" + 4) + $0
[00000000009568E2] IdStackWindows.TIdStackWindows.Connect (Line 2072, "IdStackWindows.pas" + 21) + $0
[000000000099BE3B] IdSocketHandle.TIdSocketHandle.Connect (Line 296, "IdSocketHandle.pas" + 2) + $0
[00000000009A1763] IdIOHandlerStack.TIdConnectThread.Execute (Line 488, "IdIOHandlerStack.pas" + 2) + $11
[000000000054E4A3] System.Classes.ThreadProc (Line 15573, "System.Classes.pas" + 18) + $E
[0000000000411A1D] System.ThreadWrapper (Line 25380, "System.pas" + 9) + $7
[00007FFC6CC67034] BaseThreadInitThunk + $14
[00007FFC6CE02651] RtlUserThreadStart + $21