zoukankan      html  css  js  c++  java
  • 设计并实现并发型 Echo 服务器 (Linux网络编程实践)

    Echo服务器

    设计并实现并发型 Echo 服务器 按照 RFC 862 协议规定,实现并发型 Echo 服务器应用。 要求给出服务端及客户端应用程序。采用守护进程实现。

    思路

    ​ 简单的TCP协议,没啥好讲的,实现就行。对于每一个链接,fork出一个子进程持续处理。注意通过 (recv) 的返回值判断断开连接。守护进程把原来的main函数封装进daemon就行了。

    ​ 守护进程不会在前台,想关掉请 (top) 一下,找到进程然后 $ kill -9 id $ 就行。如果发现端口占用绑定失败,请看看是否有挂在后台的进程占用了端口。

    代码部分

    $ server.c $

    #include<stdio.h>
    #include<unistd.h>
    #include<sys/socket.h>
    #include<sys/types.h>
    #include<netinet/in.h>
    #include<stdlib.h>
    #include<string.h>
    #include<arpa/inet.h>
    void Error(char str[]){
    	printf("%s error!
    ",str);
    	exit(-1);
    }
    int main(int argc,char* argv[]){
    	int s_fd,c_fd,ret;
    	struct	sockaddr_in s_addr,c_addr;
        socklen_t c_len=sizeof(c_addr);
    	char buf[256];
    	char ip[20]={0};
    	s_fd=socket(AF_INET,SOCK_STREAM,0);
    	if(s_fd<0)Error("socket");
    	memset(&s_addr,0,sizeof(s_addr));
    	s_addr.sin_family=AF_INET;
    	s_addr.sin_port=htons(8000);
    	s_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    	ret=bind(s_fd,(struct sockaddr*)&s_addr,sizeof(s_addr));
    	if(ret==-1)Error("bind");
    	ret=listen(s_fd,7);
    	if(ret)Error("listen");
    	int pid=0;
    	while(1){
    		c_fd=accept(s_fd,(struct sockaddr*)&c_addr ,&c_len );
    		if(c_fd<0)Error("accept!");
    		pid=fork();
    		if(pid==0)break;
    	}
    	printf("a client has Connected!
    ");
    	fflush(stdout);
    	int tot=0;
    
    	while(1){
    		ret=recv(c_fd,buf,(size_t)255,0);
    		buf[ret]=0;
    		printf("from:%s:%d,tot:%d recv:%s
    ",inet_ntoa(c_addr.sin_addr),(int)c_addr.sin_port,++tot,buf);
    		send(c_fd,buf,ret,0);
    		if(ret==0)break;
    		sleep(1);
    	}
    	printf("from:%s:%d client closed
    ",inet_ntoa(c_addr.sin_addr),(int)c_addr.sin_port);
    	return 0;
    }
    
    

    守护进程版本

    #include<stdio.h>
    #include<unistd.h>
    #include<sys/socket.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<netinet/in.h>
    #include<stdlib.h>
    #include<string.h>
    #include<arpa/inet.h>
    void Error(char str[]){
    	printf("%s error!
    ",str);
    	exit(-1);
    }
    void work();
    int daemon_init(void){
    	pid_t pid;
    	if((pid=fork())<0)return -1;
    	else if(pid!=0){
    		exit(0);
    	}
    	setsid();
    	chdir("/");
    	umask(0);
    	work();
    	return 0;
    }
    void work(){
    	int s_fd,c_fd,ret;
    	struct	sockaddr_in s_addr,c_addr;
        socklen_t c_len=sizeof(c_addr);
    	char buf[256];
    	char ip[20]={0};
    	s_fd=socket(AF_INET,SOCK_STREAM,0);
    	if(s_fd<0)Error("socket");
    	memset(&s_addr,0,sizeof(s_addr));
    	s_addr.sin_family=AF_INET;
    	s_addr.sin_port=htons(8000);
    	s_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    	ret=bind(s_fd,(struct sockaddr*)&s_addr,sizeof(s_addr));
    	if(ret==-1)Error("bind");
    	ret=listen(s_fd,7);
    	if(ret)Error("listen");
    	int pid=0;
    	while(1){
    		c_fd=accept(s_fd,(struct sockaddr*)&c_addr ,&c_len );
    		if(c_fd<0)Error("accept!");
    		pid=fork();
    		if(pid==0)break;
    	}
    	int tot=0;
    
    	while(1){
    		ret=recv(c_fd,buf,(size_t)255,0);
    		buf[ret]=0;
    		send(c_fd,buf,ret,0);
    		if(ret==0)break;
    		sleep(1);
    	}
    }
    
    int main(int argc,char* argv[]){
    	return daemon_init();
    }
    
    

    客户端两个方式没啥区别。

    #include<stdio.h>
    #include<unistd.h>
    #include<sys/socket.h>
    #include<arpa/inet.h>
    #include<sys/types.h>
    #include<netinet/in.h>
    #include<stdlib.h>
    #include<string.h>
    void Error(char *str){
    	printf("%s error!
    ",str);
    	exit(-1);
    }	
    int main(int argc,char* argv[]){
    	int s_fd,ret;
    	char r_buf[256], s_buf[256],ip[40];
    	struct sockaddr_in s_addr;
    	printf("please input server ip
    ");
    	scanf("%s",ip);
    	ret=s_fd=socket(AF_INET,SOCK_STREAM,0);
    	if(ret<0)Error("socket");
    	memset(&s_addr,0,sizeof(s_addr));
    	s_addr.sin_family=AF_INET;
    	s_addr.sin_port=htons(8000);
    	s_addr.sin_addr.s_addr=inet_addr(ip);
    	ret=connect(s_fd,(struct sockaddr*)&s_addr,sizeof(s_addr));
    	if(ret<0)Error("connect");
    	printf("Connect!");
    	while(1){
    		scanf("%s",s_buf);
    		send(s_fd,s_buf,strlen(s_buf),0);
    		ret=recv(s_fd,r_buf,255,0);
    		r_buf[ret]=0;
    		printf("recv:%s
    ",r_buf);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    java中goto语句
    随机产生一个小写字母
    java移位操作符注意的问题
    +号操作符
    类名引用static变量好处
    自己做题的简单的算法
    read()方法读取的是一个字节,为什么返回是int,而不是byte
    一道判断题
    关于继承中静态代码块,构造代码块,构造函数执行顺序
    比较好的Redux和React-Redux学习资料
  • 原文地址:https://www.cnblogs.com/greenpepper/p/14153333.html
Copyright © 2011-2022 走看看