2017-07-26 49 views
0

我試圖測試我的網站可以處理的流量,因此我創建了一個C程序來發送一堆連續的請求到我的網站(可能不是最好的方式,但我這樣做只是因爲我不知道C,不是因爲我真的需要測試負載處理)。下面是相關的代碼(如果你真的覺得你需要完整的源代碼,請參閱here):unistd write()在連續100次套接字寫入/讀取後停止寫入,程序返回3328錯誤代碼

while(1) { 
     sleep(1); 
     write(socket_id, request, strlen(request)); 
     read(socket_id, message, 1024 * 1024); 
} 

其中socket_id是既定的插座連接的ID,request是HTTP請求發送,並messageread的結果將被存儲。這是HTTP GET請求:

GET/HTTP/1.1 
Host: website.com 
From: ... 

我通過php腳本在我的網站上跟蹤視圖。

不管線程sleep多長時間,在寫入/讀取100次後仍然崩潰。爲什麼是這樣?

+0

你讀過[this](https://en.wikipedia.org/wiki/HTTP_persistent_connection)嗎? – jeff6times7

+1

'write'和'read'返回的值是什麼,如果失敗,errno的值是多少? (提示:使用'perror()'函數) – purplepsycho

+0

@ jeff6times7 HTTP 1.1(我正在使用的)默認是持久的。你建議使用還是不使用持久性? –

回答

0

服務器可能會關閉一個連接,因此您必須測試來自寫入和讀取函數的返回代碼,並且如果出現故障,請重新建立連接。

+0

返回值總是有效的(從不是'-1'),所以這不是問題。 –

+1

@MuhammadYojer:'0'怎麼樣? – alk

3

您的代碼很糟糕,因爲您從不測試讀寫的返回值,所以您可以在服務器端關閉後嘗試訪問套接字,但這不會導致崩潰。

但看你的github上的代碼後,我注意到,你在中包含2個不同的C文件.h文件中定義struct sockaddr_in servaddr;。確實有些編譯器可以允許它,但它不符合C,因爲它不尊重一個定義規則。實際上,您在一個導致未定義行爲的程序中定義了兩次相同的變量。

正確的方法是,以聲明該變量作爲外部在包含文件:extern struct sockaddr_in servaddr;,只有限定它在一個單獨的C文件。在你當前的源代碼中,你甚至可以只在connector.c文件中聲明它。

但是一般來說,全局變量是一場噩夢,因爲它們可能會在意想不到的時間從意想不到的地方改變,並導致使用錯誤的值。應在connector.c中聲明至少servaddr靜態。

+0

我檢查了返回值,它們總是有效的(從不'-1)。另外,我將'servaddr'從'connector.h'移動到'connector.c',並聲明它是靜態的,但是沒有任何改變;在寫入100個請求後,寫入操作仍然停止。你可以看到更新的源代碼[這裏](https://github.com/MuhammadYojer/simple-load-tester)。 –

+1

@MuhammadYojer:不,您不檢查** all **的讀取和寫入的返回值,但僅檢查每秒,並從對等關閉的套接字讀取將返回0.爲什麼不使用常見的'cr =讀(...); if(cr <= 0){...}'? –

0

read/write每次調用應進行測試,並連接應在錯誤被重建:

在文件main.c,而不是

//set up the connection 
socket_id = get_socket(); 
get_ip_address("example.com"); 
establish_connection(socket_id); 
/*...*/ 
//send the request 
while(1) { 
    if(write(socket_id, request, strlen(request)) == -1 || read(socket_id, message, 1024 * 1024) == -1) { 
     establish_connection(socket_id); 
     write(socket_id, request, strlen(request)); 
     read(socket_id, message, 1024 * 1024); 
    }else { 
     write(socket_id, request, strlen(request)); 
     read(socket_id, message, 1024 * 1024); 
    } 
} 

你應該寫類似:

/* query should be declared before this point */ 
while (1) 
{ 
    /* set up the connection */ 
    socket_id = get_socket(); 
    get_ip_address("example.com"); 
    establish_connection(socket_id); 

    /* send the request */ 
    while (1) 
    { 
     if (write(socket_id, request, strlen(request))<=0) 
     { 
      /* something goes wrong while writing, exit the inner while loop */ 
      perror("write"); 
      break; 
     } 
     if (read(socket_id, message, 1024 * 1024)<=0) 
     { 
      /* something goes wrong while reading, exit the inner while loop */ 
      perror("read"); 
      break; 
     } 
    } 
    /* if this point is reach, that means that one write or read call goes wrong */ 
    close(socket_id); 
} 
相關問題