Linux学习之网络编程(多进程并发服务器)
2018-11-07 13:19
645 查看
言之者无罪,闻之者足以戒。 - “诗序”
上面我们所说过的通信都是一个服务器一个客户端之间的通信,下面我们来交流一下多进程并发服务器的相关知识
逻辑上就是这个样子的,就是一个服务器多个客户端进行数据的传输。
1、发送数据的函数:
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
第一个参数:是由socket函数返回的套接字描述符
第二个参数:要发送的数据
第三个参数:要发送的数据的大小
第四个参数:一个标志位(具体的取值下面会给出一个表格)
2、接收数据的函数:
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
第一个参数:是由socket函数返回的套接字描述符
第二个参数:接收数据的存储位置
第三个参数:接收的字节数
第四个参数:一个标志位(具体的取值下面会给出一个表格)
flags | 说明 | recv | send |
MSG_DONTROUTE | 不查路由表 | yes | |
MSG_DONTWAIT | 本操作不阻塞 | yes | yes |
MSG_OOB | 发送或接收带外数据 | yes | yes |
MSG_WAITALL | 查看外来消息 | yes | |
MSG_PEEK | 等待所有数据 | yes |
下面看一下多进程并发服务器的流程图:
命令: ps aux|grep server
查看server的数量
下面来看一下程序:
[code]#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <fcntl.h> #include <signal.h> //最大连接数 #define MAX_LISTEN_QUE 5 //端口号 #define SERV_PORT 8888 //数组的最大字节数 #define MAX_BUFFER_SIZE 100 //创建套接字函数 int mz_ipv4_tcp_create_socket(void) { int listenfd, sockfd, opt = 1; struct sockaddr_in server, client; socklen_t len; int timep; int ret; //创建套接字 listenfd = socket(AF_INET, SOCK_STREAM, 0);//IPv4,全双工通信 if(listenfd < 0){ perror("Create socket fail."); return -1; } //设置地址的重用 if((ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0){ perror("Error, set socket reuse addr failed"); return -1; } //初始化清零操作 bzero(&server, sizeof(server)); server.sin_family = AF_INET;//IPv4 server.sin_port = htons(SERV_PORT);//端口号 server.sin_addr.s_addr = htonl(INADDR_ANY);//设置为所有都可连接 //获得结构体地址长度 len = sizeof(struct sockaddr); //套接字与服务器接口绑定 if(bind(listenfd, (struct sockaddr *)&server, len)<0){ perror("bind error."); return -1; } //设置最大连接数 listen(listenfd, MAX_LISTEN_QUE); //返回套接字 return listenfd; } //数据处理函数 int mz_process_data(int sockfd) { int bytes; char buf[MAX_BUFFER_SIZE], read_buf[MAX_BUFFER_SIZE]; //清空数组 memset(buf, 0x00, MAX_BUFFER_SIZE); while(1){ //清空数组 memset(read_buf, 0x00, MAX_BUFFER_SIZE); //从通信套接字中接收数据,并 存到read_buf中 bytes = recv(sockfd, read_buf, 100, 0); if(bytes < 0){ printf("read err.\n"); return -1; } if(bytes == 0){ printf("client connection closed.\n"); return 0; } printf("Bytes:%d\n", strlen(read_buf));//打印read_buf的长度 printf("read_buf: %x %x %x \n", read_buf[0], read_buf[1], read_buf[2]);//打印read_buf的前三个的内容 //将读取到的内容发送到通信套接字中 send(sockfd, read_buf, bytes, 0); //比较接收的数据是不是'q' if(!strcmp(read_buf, "q")){ return 0; } //比较接收的数据是不是'c' if(!strcmp(read_buf, "c")){ printf("i love you.\n"); sprintf(read_buf, "%s","i love you.\n" ); send(sockfd, read_buf, 12, 0); } } //关闭通信套接字 close(sockfd); return 0; } //信号处理函数 int mz_process_signal(int signo) { //判断信号的类型 switch(signo){ case SIGCHLD: printf("dddddddddd\n"); while(waitpid(-1, NULL, WNOHANG)>0); break; } } //创建信号处理的句柄 int mz_set_signal_handler(void) { struct sigaction act, oact; act.sa_handler = (void *)mz_process_signal;//将信号处理函数的句柄赋值给handler sigemptyset(&act.sa_mask);//清空信号集 act.sa_flags = 0; act.sa_flags |= SA_RESTART; //定义要处理的信号和处理方法 if(sigaction(SIGCHLD, &act, &oact) < 0){ return -1; } return 0; } int main(int argc, char *argv[]) { int listenfd, sockfd; struct sockaddr_in server, client; socklen_t len; int bytes =0 ; //调用创建信号句柄函数 mz_set_signal_handler(); len = sizeof(struct sockaddr); //调用套接字处理函数 listenfd = mz_ipv4_tcp_create_socket(); while(1){ //服务器等待客户端连接 sockfd = accept(listenfd, (struct sockaddr *)&client, &len); if(sockfd < 0){ perror("accept error."); return -1; } printf("sockfd=%d\n", sockfd); //打印客户端地址和端口号 printf("IP: 0x%x, Port:%d\n", ntohl(client.sin_addr.s_addr), ntohs(client.sin_port)); //创建子进程 if(fork() == 0){ //关闭套接字 close(listenfd); //调用数据处理函数 mz_process_data(sockfd); exit(0); } //关闭通信套接字 close(sockfd); } return 0; }
阅读更多
相关文章推荐
- 【嵌入式Linux学习七步曲之第七篇 Linux的高级应用编程】网络编程中并发服务器的设计模式
- linux网络编程多进程并发服务器
- linux网络编程----->高并发--->多进程并发服务器
- Linux网络编程之简单并发服务器
- 网络编程(5)多进程并发服务器
- linux网络编程----->高并发--->多线程并发服务器
- 网络编程(6)单进程多线程并发服务器实现
- Linux网络编程之简单并发服务器
- Linux 网络编程——并发服务器的三种实现模型
- [Linux网络编程] 并发服务器的实现
- 【Linux网络编程】并发服务器的三种实现模型
- linux网络编程并发进程,select和epoll(一)
- linux网络编程----->高并发--->epoll多路I/O转接服务器
- Linux 网络编程——并发服务器的三种实现模型
- linux网络编程:并发服务器的模型
- 网络编程学习_简单的多进程并发服务器/客户端
- Linux网络编程:TCP服务器(单进程多用户),使用select方法实现
- 【Linux的高级应用编程】网络编程中并发服务器的设计模式
- Linux网络编程服务器模型选择之IO复用循环并发服务器
- linux网络编程并发进程,select和epoll(二)