这段代码毁了我一整天。基本上我有一个我管理的50个web服务器的列表,我想检查它们是否为up / alive(isAlive()函数),我用50 ips / hostnames解析我的webservers.txt文件,并且为了坚牢,我尝试使用线程(10 ,20或30没关系)然后我的编译代码似乎只是退出而没有做任何事情......任何想法/帮助?
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <winsock.h>
#include <process.h>
#include <string.h>
#pragma comment(lib, "wsock32.lib")
unsigned int _stdcall isAlive(void *ptr)
{
struct sockaddr_in blah;
struct hostent *he;
WSADATA wsaData;
int i;
WORD wVersionRequested;
SOCKET sock;
char* addr = (char*)ptr;
char buff[1024];
char *ex;
ex="GET /alive.php HTTP/1.0\n\n";
char *fmsg="ALIVE";
wVersionRequested = MAKEWORD(1, 1);
if (WSAStartup(wVersionRequested , &wsaData)){
printf("Winsock Initialization failed.\n");
return(1);
}
if ((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){
printf("Can not create socket.\n");
return(1);
}
sock = socket(AF_INET,SOCK_STREAM,0);
blah.sin_family = AF_INET;
blah.sin_port = htons(80);
blah.sin_addr.s_addr = inet_addr(addr);
if ((he=gethostbyname(addr))!=NULL){
memcpy((char *)&blah.sin_addr.s_addr,he->h_addr,he->h_length);
}
else{
if((blah.sin_addr.s_addr=inet_addr(addr))==-1){
WSACleanup();
return(1);
}
}
if (connect(sock,(struct sockaddr*)&blah,sizeof(blah))==0){
send(sock,ex,strlen(ex),0);
recv(sock,buff,sizeof(buff),0);
if(strstr(buff,fmsg)!=NULL){
printf("ALIVE: %s", addr);
}
}
closesocket(sock);
WSACleanup();
_endthreadex(0);
return(1);
}
int main(int argc,char *argv[])
{
if(argc!=2){
printf("Usage: %s <webservers list>\n", argv[0]);
return(1);
}
char *inname = argv[1];
FILE *infile;
char line_buffer[BUFSIZ];
char line_number;
infile = fopen(inname, "r");
if (!infile) {
printf("Couldn't open file %s for reading.\n", inname);
return 0;
}
line_number = 0;
HANDLE hThreadArray[200];
while (fgets(line_buffer, sizeof(line_buffer), infile)) {
++line_number;
unsigned threadID;
hThreadArray[line_number] = (HANDLE)_beginthreadex(0, 0, isAlive, line_buffer, 0, &threadID);
}
WaitForMultipleObjects(sizeof(line_buffer), hThreadArray, TRUE, INFINITE);
return 0;
}
建议后的新代码:
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <winsock.h>
#include <process.h>
#include <string.h>
#pragma comment(lib, "wsock32.lib")
unsigned int _stdcall isAlive(void *ptr)
{
struct sockaddr_in blah;
struct hostent *he;
WSADATA wsaData;
int i;
WORD wVersionRequested;
SOCKET sock;
char* addr = (char*)ptr;
char buff[1024];
char *ex;
ex="GET /alive.php HTTP/1.1\n\n";
char *fmsg="ALIVE";
wVersionRequested = MAKEWORD(1, 1);
if (WSAStartup(wVersionRequested , &wsaData)){
printf("Winsock Initialization failed.\n");
return(1);
}
if ((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){
printf("Can not create socket.\n");
return(1);
}
sock = socket(AF_INET,SOCK_STREAM,0);
blah.sin_family = AF_INET;
blah.sin_port = htons(80);
blah.sin_addr.s_addr = inet_addr(addr);
if ((he=gethostbyname(addr))!=NULL){
memcpy((char *)&blah.sin_addr.s_addr,he->h_addr,he->h_length);
}
else{
if((blah.sin_addr.s_addr=inet_addr(addr))==-1){
WSACleanup();
return(1);
}
}
if (connect(sock,(struct sockaddr*)&blah,sizeof(blah))==0){
send(sock,ex,strlen(ex),0);
recv(sock,buff,sizeof(buff),0);
if(strstr(buff,fmsg)!=NULL){
printf("ALIVE: %s\n", addr);
}
}
closesocket(sock);
WSACleanup();
_endthreadex(0);
return(1);
}
int main(int argc,char *argv[])
{
if(argc!=2){
printf("Usage: %s <webservers list>\n", argv[0]);
return(1);
}
char *inname = argv[1];
FILE *infile;
char line_buffer[10000];
char line_number;
infile = fopen(inname, "r");
if (!infile) {
printf("Couldn't open file %s for reading.\n", inname);
return 0;
}
line_number = 0;
HANDLE hThreadArray[200];
while (fgets(line_buffer, sizeof(line_buffer), infile)) {
unsigned threadID;
hThreadArray[line_number] = (HANDLE)_beginthreadex(0, 0, isAlive, line_buffer, 0, &threadID);
++line_number;
}
WaitForMultipleObjects(line_number, hThreadArray, TRUE, INFINITE);
fclose(infile);
return 0;
}
现在我的代码运行了,但它占用了我的文本中的最后一行并创建了多个线程,我迷路了:(
hosts.txt(其中有11行)
myhost.com
mysecondhost.com
...
mylasthost.com
结果: C:\ Documents and Settings \ Xtmtrx \ Desktop \ Code&gt; checkalive.exe hosts.txt
ALIVE: mylasthost.com
ALIVE: mylasthost.com
ALIVE: mylasthost.com
ALIVE: mylasthost.com
ALIVE: mylasthost.com
ALIVE: mylasthost.com
ALIVE: mylasthost.com
ALIVE: mylasthost.com
ALIVE: mylasthost.com
ALIVE: mylasthost.com
ALIVE: mylasthost.com
如果我这样做:
#define MAX 10000
/* snip */
HANDLE hThreadArray[200];
char str[MAX];
char *x[MAX];
int i =0;
while(!feof(infile)) {
while(fgets(str, sizeof str, infile)) {
unsigned threadID;
x[i] = strdup(str);
printf("%s", *(x+i));
hThreadArray[i] = (HANDLE)_beginthreadex(0, 0, isAlive, *(x+i), 0, &threadID);
i++;
}
}
会不会?
最后编辑:
这是我完成的代码,似乎工作,我也添加了超时但似乎没有考虑因为它可以挂在一些主机上:
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <winsock.h>
#include <process.h>
#include <string.h>
#pragma comment(lib, "wsock32.lib")
#define MAX 10000
unsigned int _stdcall isAlive(void *ptr)
{
struct sockaddr_in blah;
struct hostent *he;
WSADATA wsaData;
int i;
WORD wVersionRequested;
SOCKET sock;
char* addr = (char*)ptr;
char buff[1024];
char *request;
request="GET /alive.php HTTP/1.0\n\n";
char *fmsg="ALIVE";
wVersionRequested = MAKEWORD(1, 1);
if (WSAStartup(wVersionRequested , &wsaData)){
printf("Winsock Initialization failed.\n");
return(1);
}
if ((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){
printf("Can not create socket.\n");
return(1);
}
sock = socket(AF_INET,SOCK_STREAM,0);
blah.sin_family = AF_INET;
blah.sin_port = htons(80);
blah.sin_addr.s_addr = inet_addr(addr);
if ((he=gethostbyname(addr))!=NULL){
memcpy((char *)&blah.sin_addr.s_addr,he->h_addr,he->h_length);
}
else{
if((blah.sin_addr.s_addr=inet_addr(addr))==-1){
WSACleanup();
return(1);
}
}
if (connect(sock,(struct sockaddr*)&blah,sizeof(blah))==0){
send(sock,request,strlen(request),0);
recv(sock,buff,sizeof(buff),0);
if(strstr(buff,fmsg)!=NULL){
printf("ALIVE: %s", addr);
}
}
closesocket(sock);
WSACleanup();
_endthreadex(0);
return(1);
}
int main(int argc,char *argv[])
{
if(argc!=2){
printf("Usage: %s <webservers list>\n", argv[0]);
return(1);
}
char *inname = argv[1];
FILE *infile;
char line_buffer[BUFSIZ];
char line_number;
infile = fopen(inname, "r");
if (!infile) {
printf("Couldn't open file %s for reading.\n", inname);
return 0;
}
HANDLE hThreadArray[200];
char str[MAX];
char *x[MAX];
int i = 0;
while(!feof(infile)) {
while(fgets(str, sizeof str, infile)) {
unsigned threadID;
x[i] = strdup(str);
//printf("%s", *(x+i)); // DEBUG
hThreadArray[i] = (HANDLE)_beginthreadex(0, 0, isAlive, *(x+i), 0, &threadID);
i++;
}
}
WaitForMultipleObjects(i, hThreadArray, TRUE, INFINITE);
fclose(infile);
return 0;
}
任何想法/想法?
答案 0 :(得分:3)
您的代码存在很多问题,尤其是:
WaitForMultipleObjects的第一个参数需要NUMBER个元素,而不是缓冲区的SIZE。改为使用line_number。
您的循环从不设置数组的第一个元素(元素0),因为在通过hThreadArray [line_number]设置之前将line_number增加为1。
您正在将指向堆栈分配缓冲区(line_buffer)的指针作为线程的参数传递。然后在线程启动之前继续更改此堆栈缓冲区。作为线程起始参数发送的参数需要在堆上分配(每个线程一个,线程负责以后释放它)。
您实际上从未检查过_beginThreadEx的响应代码,因此您无法确定该线程是否已启动!
您的主题开头没有任何printf语句。把它放在那里可以帮助你调试你的线程是否一直在启动。
服务器的HTTP参数可能会失败。在Wireshark中查看真实的GET请求是什么样的并复制它。您至少应该发送带有主机头的HTTP / 1.1。
尽管先调用WSAStartup(),但新的线程代码中仍有一些路径不会调用WSACleanup()。
答案 1 :(得分:1)
考虑当主线程继续使用循环之前会发生什么,它刚刚启动的线程会有用。
它将覆盖line_buffer
处的内存,这就是它将要执行的操作。这将在线程有机会查看之前更改内存。换句话说,请考虑此时间表:
main populates linebuffer
main starts thread 1
thread1 starts
main populates linebuffer
thread1 reads linebuffer
你可以看到缓冲区在线程查看之前已经发生了变化。
如果要在这样的线程之间共享数据,则需要确保它们正确地序列化访问。有几种方法可以做到这一点,其中一些方法如下:
main
不会覆盖先前发送的。{/ li>
main
之间使用某种形式的通信,以便main
等待线程制作本地副本,然后再继续。此外,我不确定您的WaitForMultipleObjects
应该使用sizeof(line_buffer)
作为对象计数。当然line_number
将是一个更好的选择,因为这是你创建的对象的实际数量。