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;
    }
    
    
  • 相关阅读:
    delphi7在windows server 2003企业版上不能打开项目的选项(Options)窗口的解决方法
    简单的两个字“谢谢”,会让我坚持我的写作,我也要谢谢你们
    F41GUT 安装Windows server 2003系统后无法安装显卡驱动的解决办法
    远程桌面无法登录windows server 2003服务器
    F41GUT 安装Windows server 2003系统后无法安装显卡驱动的解决办法
    MS SQL Server 2000版在windows server 2003企业版系统上运行时造成数据库suspect的解决方法
    delphi7在windows server 2003企业版上不能打开项目的选项(Options)窗口的解决方法
    远程桌面无法登录windows server 2003服务器
    MS SQL Server 2000版在windows server 2003企业版系统上运行时造成数据库suspect的解决方法
    关于ajax 和josn
  • 原文地址:https://www.cnblogs.com/greenpepper/p/14153333.html
Copyright © 2011-2022 走看看