网络编程-----多进程并发服务器实现

案例要求

  1. 实现一个多进程并发的服务器,可以实现多个客户端的连接。
  2. 把每个连接的客户端的ip和port输出,而且每个客户端的输入都在服务器输出
  3. 把客户端的小写转化为大写

声明:因个人能力有限,本文仅是个人的学习记录笔记,有错误之处还望指出

原理图
在这里插入图片描述

实现流程

  1. 新建socket  socket(int domain, int type, int protocol)
  2. 绑定连接(初始化客户端的sockaddr结构体) bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  3. 设置链接上限  listen(int sockfd, int backlog)
  4. 阻塞等待链接,并且返回客户端的sockfd accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
  5. 有新的客户端链接就创建线程 fork

    当fork的返回值>0,是父进程,负责回收子进程(利用信号)
    当fork的返回值<0,是子进程,负责处理数据(利用信号)

代码实现

#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <strings.h>
#include <ctype.h>
#include <sys/wait.h>
#include <stdlib.h>

//定义服务器端口
#define SERV_PORT 8888

//定义服务器IP
#define SERV_IP  "127.0.0.1"

/*	服务器链接过程

	1.建立套接字   				--->socket
	2.绑定套接字,并且初始化套接字结构体    --->bind
	3.设置连接上限  		        --->listen
	4.阻塞等待链接 				--->accept
	5.读取客户端套接字的数据                --->read
	6.处理数据   				--->toupper
	7.将数据修改                		--->write

*/
void *wait_child(int signal){
	
	while( waitpid(0,NULL,WNOHANG)> 0)

	return 0;
}

int main(){
	
	//定义客户端和服务器的套接字,循环因子,从缓冲区读到的字节数
	int sfd,cfd,i,n;
	
	pid_t pid;	


	unsigned  char ip_buf[sizeof(struct in_addr)];

	char buf[BUFSIZ],client_ip[BUFSIZ];
	
	//定义客户端和服务器的套接字结构体
	struct sockaddr_in serv_addr,client_addr;

	//初始化客户端结构体
	bzero(&client_addr,sizeof(client_addr));

	//服务器结构体赋值
	serv_addr.sin_family = AF_INET;//IPV4模式
	serv_addr.sin_port = htons(SERV_PORT);//PORT ---->注意网络字节序
	//此处和前面不一样,用inet_pton已经把结构体里面的ip修改
	inet_pton(AF_INET,SERV_IP,ip_buf);//IP ---->注意网络字节序

//	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//IP ---->注意网络字节序

	//新建socket
	sfd = socket(AF_INET,SOCK_STREAM,0);

	//绑定链接
	bind(sfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));

	//设置上限
	listen(sfd,128);

	//阻塞等待
	socklen_t client_addr_len;
	client_addr_len = sizeof(client_addr);

	//循环等待连接,并打印客户端信息
while(1){
	cfd = accept(sfd,(struct sockaddr *)&client_addr,&client_addr_len);
	
	//打印客户端的ip和port
	//INET——ADDRSTRLEN是操作系统指定的ipv4的str长度的宏
	printf("client ip : %s client port :%d\n",
	inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip,INET_ADDRSTRLEN),
	ntohs(client_addr.sin_port)
	);
	
	
	pid = fork();
	
	if( pid < 0){
	perror(" fork");
	exit(1);
	}
	//子进程要操作客户端sock文件描述符,关闭服务器文件描述符
	else if( pid == 0){
	close(sfd);
	break;
	}
	else{

	close(cfd);
	signal(SIGCHLD,wait_child);
	}
}
	
	if( pid == 0){
	//循环读取数据
	while(1){

	n = read(cfd,buf,sizeof(buf));

	//循环处理所有数据
	for(i = 0;i < n;i++){

	buf[i] = toupper(buf[i]);	

	}

	write(cfd,buf,n);
	write(STDOUT_FILENO,buf,n);


	}
	}
	
	return 0;
}

结果图

在这里插入图片描述

因为在同一台虚拟机下故ip一样,但端口号是不同的

而塞过 2021-1-11

关于我:一个就要进入互联网,经历社会毒打的99小伙

下一站(javascript)
下一站(html)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值