GlooK
24.10.2009, 05:09
Нужна помощь в понимании потоков :)
До этого момента писал софт однопоточный. Сейчас хочу научиться писать многопоточные программы.
Как я понимаю есть несколько реализаций. Знаю что можно написать используя класс TThread и CreateThread (или как пишут, правильней через BeginThread).
Интересует именно CreateThread.
Есть например такой код:
program threads;
{$APPTYPE CONSOLE}
uses
SysUtils,
WinSock;
const
mstimeout = 10000;
buffsize = 1024;
var
hSocket: TSocket;
FData: string;
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;
begin
FData := fWSRecv('google.ru',
'GET /search?q=abc' + #13#10 +
'Host: google.ru' + #13#10 +
'User-Agent: Mozilla/5.0' + #13#10 +
'Accept: text/html' + #13#10 +
'Accept-Language: ru' + #13#10 +
'Accept-Charset: windows-1251' + #13#10 +
'Connection: close' + #13#10#13#10);
Writeln;
Writeln('Done!');
readln;
end.
Как сделать его многопоточным?
Я попробовал так:
program threads;
{$APPTYPE CONSOLE}
uses
SysUtils,
WinSock,
Windows;
const
mstimeout = 10000;
buffsize = 1024;
var
hSocket: TSocket;
FData: string;
wsData: TWSAData;
idThread: integer;
HThread: array[0..20] of THandle;
function fWSRecv(wHost, wRequest: string):string;
var
hHost: PHostEnt;
hAddr: TSockAddrIn;
hTimeout: TTimeVal;
iRead: integer;
hData: string;
hBuffer: array[0..buffsize] of char;
begin
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);
result := hData;
end;
function fThread(ptr: pointer):integer;
begin
FData := fWSRecv('google.ru',
'GET /search?q=abc' + #13#10 +
'Host: google.ru' + #13#10 +
'User-Agent: Mozilla/5.0' + #13#10 +
'Accept: text/html' + #13#10 +
'Accept-Language: ru' + #13#10 +
'Accept-Charset: windows-1251' + #13#10 +
'Connection: close' + #13#10#13#10);
ExitThread(0);
result := 0;
end;
begin
WSAStartup($202, wsData);
for idThread := 0 to 10 do
HThread[idThread] := CreateThread(nil, 0, @fThread, nil, 0, HThread[idThread]);
//WSACleanup;
Writeln;
Writeln('Done!');
readln;
end.
Но запросы не отправляются.
Имеет ли вообще данный код право на жизнь?
Можно ли так свободно использовать функции в потоке?
Если есть, дайте линки на исходники программ с использованием Winsock + CreateThread.
До этого момента писал софт однопоточный. Сейчас хочу научиться писать многопоточные программы.
Как я понимаю есть несколько реализаций. Знаю что можно написать используя класс TThread и CreateThread (или как пишут, правильней через BeginThread).
Интересует именно CreateThread.
Есть например такой код:
program threads;
{$APPTYPE CONSOLE}
uses
SysUtils,
WinSock;
const
mstimeout = 10000;
buffsize = 1024;
var
hSocket: TSocket;
FData: string;
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;
begin
FData := fWSRecv('google.ru',
'GET /search?q=abc' + #13#10 +
'Host: google.ru' + #13#10 +
'User-Agent: Mozilla/5.0' + #13#10 +
'Accept: text/html' + #13#10 +
'Accept-Language: ru' + #13#10 +
'Accept-Charset: windows-1251' + #13#10 +
'Connection: close' + #13#10#13#10);
Writeln;
Writeln('Done!');
readln;
end.
Как сделать его многопоточным?
Я попробовал так:
program threads;
{$APPTYPE CONSOLE}
uses
SysUtils,
WinSock,
Windows;
const
mstimeout = 10000;
buffsize = 1024;
var
hSocket: TSocket;
FData: string;
wsData: TWSAData;
idThread: integer;
HThread: array[0..20] of THandle;
function fWSRecv(wHost, wRequest: string):string;
var
hHost: PHostEnt;
hAddr: TSockAddrIn;
hTimeout: TTimeVal;
iRead: integer;
hData: string;
hBuffer: array[0..buffsize] of char;
begin
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);
result := hData;
end;
function fThread(ptr: pointer):integer;
begin
FData := fWSRecv('google.ru',
'GET /search?q=abc' + #13#10 +
'Host: google.ru' + #13#10 +
'User-Agent: Mozilla/5.0' + #13#10 +
'Accept: text/html' + #13#10 +
'Accept-Language: ru' + #13#10 +
'Accept-Charset: windows-1251' + #13#10 +
'Connection: close' + #13#10#13#10);
ExitThread(0);
result := 0;
end;
begin
WSAStartup($202, wsData);
for idThread := 0 to 10 do
HThread[idThread] := CreateThread(nil, 0, @fThread, nil, 0, HThread[idThread]);
//WSACleanup;
Writeln;
Writeln('Done!');
readln;
end.
Но запросы не отправляются.
Имеет ли вообще данный код право на жизнь?
Можно ли так свободно использовать функции в потоке?
Если есть, дайте линки на исходники программ с использованием Winsock + CreateThread.