Попал мне в руки как-то журнал хакер(мерзкий конечно,но бывает и там полезная инфа =) ) и там описывалась идея создания многопоточного сканера и я решил реализовать это на C в качестве упражнения по многозадачности и сети(это первые опыты,так что сильно не бейте.).
Пока что получилось вот что:
#include<sys/socket.h> #include<sys/types.h> #include<resolv.h> #include<stdio.h> #include<errno.h> #include<glib.h> #include<pthread.h> #include<signal.h>
#define PROCNUM 30
GList* ips; // список ip-шников
void generate_ips() { int i; for(i=1;i<255;i++) ips=g_list_append(ips,g_strdup_printf("192.168.22.%d",i)); }
void* try_ip(void* ip) { int sock; struct sockaddr_in server; memset(&server,sizeof(server),0);
server.sin_family=AF_INET; server.sin_port=htons(139); server.sin_port=htons(139); inet_aton(ip,&server.sin_addr); sock=socket(PF_INET,SOCK_STREAM,0);
if(sock<0){ printf("error %d while creating socket!\n",errno); exit(1); }
if(connect(sock,&server,sizeof(server))==0){ printf("==>%s\n",ip); close(sock); } raise(SIGCHLD); return NULL; }
void on_child_exited(int sig) { if(ips) { pthread_t child; if((pthread_create(&child,NULL,&try_ip,(void*)(ips->data)))!=0){ printf("error creating thread!\n"); } ips=ips->next; } }
int main(int argc,char* argv[]) { int ips_in_scan=0;
struct sigaction act; memset(&act,sizeof(act),0);
act.sa_handler=on_child_exited; act.sa_flags=SA_NOMASK | SA_RESTART; //не уверен с флагами sigaction(SIGCHLD,&act,0);
generate_ips(); for(;ips,ips_in_scan<PROCNUM;ips=ips->next,ips_in_scan++) { pthread_t child; if((pthread_create(&child,NULL,&try_ip,(void*)(ips->data)))!=0) { printf("error creating thread!\n"); } } sleep(100); return 0; }
Идеология следующая: сначала генерю список ip,потом начинаю его читать и создаю максимально возможное число потоков.Далее я хочу чтобы как только потомок отработает,приходил сигнал родителю и он стартовал новый поток,пока есть что сканить.Результаты потомки отдают в stdin.
Наткнулся на следующие проблемы:
1) После того как я создал первые n потоков,родителю больше нечего делать и он выходит.Во всех примерах,какие у меня были там бы вызывался waitpid(),но я не знаю pid`a того потомка,которого мне надо ждать,так как он может даже ещё не начат...
2) Как сделать timeout на процедуру connect() ? Чтобы если скажем через 5 секунд если потомок не вышел,убить его нафиг и продолжить со следующим адресом..
3) В обработчике сигнала возможно нужна блокировка доступа к списку?
4) Нужны либо какие действия по очистке после завершения потомка? я что-то так и не догнал...
5) И что происходит с теми потомками,которые не завершились,а родитель вышел без waitpid и т.п. ? zombie или как ? я что-то пока не заметил никакого эффекта в ps после запуска существующей версии..
Помогите пжалста :) ! а то я что-то совсем запутался.Если есть какие-нибудь хорошие ссылки по теме - кидайте.И ещё - может я с самого начала выбрал неправильную идеологию?