我正在尝试测试我的网站可以处理的流量,所以我创建了一个C程序,向我的网站发送一堆连续的请求(可能不是最好的方式,但我之所以这样做是因为我不喜欢我真的知道C,不是因为我真的需要测试负载处理)。以下是相关代码(如果您确实需要完整的源代码,请参阅here):
while(1) {
sleep(1);
write(socket_id, request, strlen(request));
read(socket_id, message, 1024 * 1024);
}
其中socket_id
是已建立的套接字连接的ID,request
是要发送的HTTP请求,message
将存储read
的结果。这是HTTP GET请求:
GET / HTTP/1.1
Host: website.com
From: ...
我正在通过我网站上的php脚本跟踪观看结果。
无论线程sleep
有多长,它在100次写入/读取后仍会崩溃。这是为什么?
答案 0 :(得分:3)
您的代码很糟糕,因为您从不测试读取和写入的返回值,因此在服务器端关闭后仍然可以尝试访问套接字,但这不应该导致崩溃。
但是在查看了你的github代码后,我注意到你在.h文件中定义 struct sockaddr_in servaddr;
,该文件包含在2个不同的c文件中。确实有些编译器可以允许它,但它不符合C,因为它不遵守One Definition Rule。实际上,在一个程序中定义两次相同的变量会导致未定义的行为。
正确的方法是在包含文件中将声明变量作为外部变量:extern struct sockaddr_in servaddr;
,并且只在单个c文件中定义它。在您当前的源代码中,您甚至可以只在connector.c文件中声明它。
但总的来说,全局变量是一场噩梦,因为它们可能会在意外的时间从意外的地方进行更改,从而导致使用错误的值。至少servaddr
应在connector.c中声明为静态。
答案 1 :(得分:0)
服务器可能会关闭连接,因此您必须测试写入和读取功能的返回代码,如果发生故障,请重新建立连接。
答案 2 :(得分: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);
}