參考:linux高性能server编程。作者:游双
程序简单介绍:该程序用了共享内存来实现进程间的同步,因为仅仅是同一时候读取共享内存。所以没实用到锁。该程序的功能是server监听网络连接,当有一个client连接时,server创建一个子进程处理该连接。
每一个子进程仅仅负责自己的client以及和父进程通信。当子进程从client读取数据后,把数据放到共享内存上,每一个子进程在共享内存上有自己的一段空间。因此不会出现同一时候写。
放上去后通知父进程,说:共享内存上有新数据到达了,然后父进程通知其它子进程,去到该位置读取数据,把数据发送到自己的client。实现了群聊的效果。该程序对于多进程编程的刚開始学习的人是个不错的样例,写下来是为了让自己熟悉一下。
server代码:编译的时候须要加上 -lrt选项
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#define USER_LIMIT 5
#define BUFFER_SIZE 1024
#define FD_LIMIT 65535
#define MAX_EVENT_NUMBER 1024
#define PROCESS_LIMIT 65536
/* 处理一个客户端连接的必要数据 */
struct client_data
{
sockaddr_in address;
int connfd; /* 客户端的fd */
pid_t pid; /* 处理这个连接的子进程的pid */
int pipefd[2]; /* 和父进程通信用的管道 */
};
int sig_pipefd[2];//当有信号发生时。用于父进程自己的通信
char* share_mem;
int user_count = 0; //当前客户的数量
client_data* users = 0 ;
int* sub_process = 0;
static const char* shm_name = "/my_share_memory";
int maxevents = 100;
bool stop_child = false;
void setnonblock(int fd)
{
int flag = fcntl(fd,F_GETFL);
assert(flag != -1);
fcntl(fd,F_SETFL,flag | O_NONBLOCK);
}
void addfd(int epollfd,int fd)
{
epoll_event ee;
ee.data.fd = fd;
ee.events = EPOLLIN | EPOLLET;
epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&ee);
setnonblock(fd);
}
void sig_handler(int sig)
{
int save_errno = errno;
int msg = sig;
send(sig_pipefd[1],(char*)&msg,1,0);
errno = save_errno;//恢复错误值
}
void child_sig_handler(int sig)
{
stop_child = true;
}
void addsig(int sig,void (*handler)(int),bool restart = true)
{
struct sigaction sa;
memset(&sa,'