简单的listen+fork accept服务器实现
Posted 重复啦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单的listen+fork accept服务器实现相关的知识,希望对你有一定的参考价值。
前段时间在分析nginx的IO模型的时候,知道nginx采用的是一进程监听+多进程accept的模式,也就是主进程先创建socket并bind指定端口listen之后,再fork出若干个子进程,由子进程去accept连接请求。
这段时间将其用代码实现并验证了一遍,监听端口后对接受到的请求,按照http协议返回进程id,算是一个极其简单的web服务器吧,后续对http协议的内容了解深入之后,看看再怎么对其扩展下。
#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> int s;//socket typedef enum//定义bool类型,c语言中没有bool类型 { false, true }bool; bool init (const char* addr, const short port) { struct sockaddr_in servaddr; s = socket(AF_INET, SOCK_STREAM, 0); if(-1 == s) return false; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; if(inet_pton(AF_INET, addr, &servaddr.sin_addr) < 0) return false; servaddr.sin_port = htons(port); if(bind(s, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) { printf("port is in use\\n"); return false; } if(listen(s, 10) == -1) return false; printf("init success! listen port %d\\n", port); return true; } void do_cycle() { int connect_fd; char rcvbuf[102400]; char sndbuf[102400]; pid_t pid = getpid(); while(true) { if((connect_fd = accept(s, (struct sockaddr*)NULL, NULL)) == -1) { printf("accept socket error\\n"); continue; } recv(connect_fd, rcvbuf, 102400, 0); snprintf(sndbuf, 102400, "HTTP/1.1 200 OK\\r\\n\\r\\n<html><head><title>hello</title></head><body>process id: %d</body></html>", pid); send(connect_fd, sndbuf, strlen(sndbuf), 0); close(connect_fd); } } void loop_cycle(int process_num) { int i, j; pid_t pid; pid_t sub_ids[process_num]; char killstr[1024]; char ch; if(1 == process_num) do_cycle(); else for (i = 0; i < process_num; i++) { pid = fork(); if(pid < 0) { printf("fork error\\n"); for(j = 0; j < i; j++) { snprintf(killstr, 1024, "kill -9 %d", sub_ids[j]); system(killstr); } return; } if(pid == 0) do_cycle(); if(pid > 0) sub_ids[i] = pid; } while(true) { scanf("%c", &ch); if(ch == \'q\') { for(j = 0; j < process_num; j++) { snprintf(killstr, 1024, "kill -9 %d", sub_ids[j]); system(killstr); } close(s); break; } } } int main(int argc, char* args[]) { int port, pro_num; if(argc < 4) { printf("usage: hs <ip> <port> <process num>\\n"); return 0; } port = atoi(args[2]); pro_num = atoi(args[3]); if(!init(args[1], port)) return 0; loop_cycle(pro_num); return 0; }
在init函数中,创建socket并进行监听,然后在loop_cycle中fork子进程,由子进程进行循环接收处理数据,父进程等待用户输入,如果用户输入退出指令,结束所有子进程并退出。
运行程序:
启动后,用浏览器访问效果:
返回了进程id.
以上是关于简单的listen+fork accept服务器实现的主要内容,如果未能解决你的问题,请参考以下文章