#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h>
#include <string.h>
#define SERV_PORT 8031
int main(void)
{
int lfd, cfd;
struct sockaddr_in serv_addr,clin_addr;
socklen_t clin_len;
pid_t pid;
char buf[1024];
int len;
if((lfd = socket(AF_INET,SOCK_STREAM,0)) == -1){
perror("create socket failed");
exit(1);
}
int opt = 1;
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(SERV_PORT);
if(bind(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
{
perror("bind error");
exit(1);
}
if(listen(lfd, 128) == -1)
{
perror("listen error");
exit(1);
}
clin_len = sizeof(clin_addr);
signal(SIGCLD,SIG_IGN);
while(1)
{
if((cfd = accept(lfd, (struct sockaddr *)&clin_addr, &clin_len)) == -1)
{
perror("accept error");
exit(1);
}
pid = fork();
if (pid > 0)
{
// 在父进程中关闭连接的套接字描述符,只是把 cfd 的引用数减少1,在子进程中还在使用 cfd
close(cfd);
}
else if (pid == 0)
{
// 子进程关闭 lfd 处理任务,使其回到 TIME_WAIT 状态值
close(lfd);
char web_result[] = "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\nContent-Length: 11\r\nServer: mengkang\r\n\r\nhello world";
write(cfd,web_result,sizeof(web_result));
close(cfd);
exit(0);
}
else
{
perror("fork error");
exit(1);
}
}
close(lfd);
return 0;
}
如果对上面的代码 ab 测试,不管多少个请求,多少并发都不行
[root@localhost ~]# ab -c1 -n1 http://127.0.0.1:8031/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient)...apr_socket_recv: Connection reset by peer (104)
直接在浏览器上访问是没问题的,怎么回事呢?是不是我某个地方写的不严谨,不符合规范?
如果把上面的代码中的多线程去掉,就能够使用 ab 了。
问题我找到了,原来是我在子进程了没有多cfd(client socket fd)执行read 操作。很诡异,在单一线程循环服务器的时候不读取则没事。http://mengkang.net/573.html
fork多进程是不可以运行在cgi模式下的。 (php是这样, c语言应该也是这样)
代码没有太大的问题呀
是不是 ab 测试的时候fork出的的进程太多(fork的效率也很低,用vfork代替),导致系统kill掉了这个进程树