在实现之前先看看我在上一篇博文浅谈linux下的进程,线程的概念与使用中,
介绍了linux的一些进程状态转换的概念以及响相应的系统调用函数,比如fork,waitpid/wait,exec函数等等
掌握了这些函数的使用,实现多进程服务器就很简单了.
整体思路就是:在子进程处理读写套接字,负责与客户端数据的收发
在父进程处理监听套接字,负责与客户端的连接
直接看源码吧
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include<arpa/inet.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
int main()
{
char buf[80];
int n;
//创建监听套接字
int listen_fd=socket(AF_INET,SOCK_STREAM,0);
//设置监听套接字
struct sockaddr_in serv_addr;//定义套接字地址结构体
bzero(&serv_addr, sizeof(serv_addr));//结构体初始化为0
serv_addr.sin_family = AF_INET;//网络格式为ipv4
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//设置ip
serv_addr.sin_port = htons(8000);//设置端口
printf("等待客户端连接...");
//绑定
if(bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))!=0)
{
perror("bind:");
}
//监听
if(listen(listen_fd, 20)!=0)
{
perror("listen:");
}
//开始
while(1)
{
//接受客户端的连接请求
struct sockaddr_in client_addr;//存放客户端地址
int cliaddr_len = sizeof(client_addr);//存放客户端地址结构体长度
int client_fd= accept(listen_fd, (struct sockaddr*)&client_addr, &cliaddr_len);//接受客户端的请求 创建io套接字
//创建子进程
int pid=fork();
if(pid<0)
{
perror("fork:");
}
//分配子进程任务--负责读写套接字
else if(pid==0)
{
close(listen_fd);//由于在子进程主要进行数据交互任务,所以关闭监听套接字;
/*读取客户端发来的数据read*/
printf("now in child process");
//if((n=read(client_fd, buf, 80))==-1)//存储读取的字节数
//{
//perror("read:");
//}
//printf("%c",buf[1]);
while((n=read(client_fd, buf, 80))!=0)
{
printf("sending data...");
int n2=write(client_fd, buf, n);//从缓存buf中读取n字节发送
if(n2==-1)
{
perror("write:");
}
}
close(client_fd);
return 0;
}
//分配父进程任务--负责监听套接字
else
{
printf("now in parent process");
close(client_fd);
waitpid(-1,NULL,WNOHANG);
}
}
//关闭监听套接字 程序结束
close(listen_fd);
return 0;
}