并发服务器

要求

修改远程控制服务器代码,使得服务器同时能够向多个用户提供服务。
消除僵尸进程,收回所有子进程资源。

注意点

了解fork函数的用法。
处理僵尸进程
signal(SIGCLD,SIG_IGN);
写在程序开头。

伪代码

/*tcpserver.c*/
int execute(char* command,char* buf);


int main(int argc,char** argv)
{
	
	signal(SIGCLD,SIG_IGN);
	
	listend=socket(AF_INET,SOCK_STREAM,0))setsockopt(listend,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

	memset(&server,0,sizeof(struct sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = htonl(INADDR_ANY);
	server.sin_port = htons(port);

	bind(listend,(struct sockaddr *)&server,sizeof(struct sockaddr))	//绑定端口


	listen(listend,5)


	while (1)
	{
		connectd=accept(listend,(struct sockaddr*)&client,&len);//等待客户端连接
		

		printf("connect  with %s:%d\n",inet_ntoa(client.sin_addr),htons(client.sin_port));
		
		int pid = fork();
		if(pid == 0){
			close(listend);

			//已建立好连接
			while(1){
					memset(send_buf,0,2048);
					memset(recv_buf,0,2048);
					
					recvnum = recv(connectd,recv_buf,sizeof(recv_buf),0);//就收客户端发来的命令
					//执行命令
					strcpy(cmd,"/bin/");
					strcat(cmd,recv_buf);
					execute(cmd,send_buf);
					
send(connectd,send_buf,sizeof(send_buf),0) //向客户端发送消息
					
				}

				printf("disconnect with %s:%d\n",inet_ntoa(client.sin_addr),htons(client.sin_port));
				return 0;
		}
	
		close(connectd);
   }


	close(listend);
	return 0;

}

代码

/*tcpserver.c*/
#include<stdlib.h>
#include<stdio.h>
#include<sys/socket.h>
#include<netdb.h>
#include<string.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <printf.h>
# include <sys/wait.h>
# include <sys/types.h>

#define PORT 8900

int execute(char* command,char* buf);

int main(int argc,char** argv)
{
	signal(SIGCLD,SIG_IGN);	//处理僵尸进程

	struct sockaddr_in server;
	struct sockaddr_in client;
	int len;
	int port;
	int listend;
	int connectd;
	int sendnum;
	int opt;
	int recvnum;
	char send_buf[2048];
	char recv_buf[2048];
	char cmd[2048];

	port= PORT;
	opt = SO_REUSEADDR;

	if (-1==(listend=socket(AF_INET,SOCK_STREAM,0)))
	{
		perror("create listen socket error\n");
		exit(1);
	}

	setsockopt(listend,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

	memset(&server,0,sizeof(struct sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = htonl(INADDR_ANY);
	server.sin_port = htons(port);

	if (-1==bind(listend,(struct sockaddr *)&server,sizeof(struct sockaddr)))	//绑定端口
	{
		perror("bind error\n");
		exit(1);
	}

	if (-1==listen(listend,5))
	{
		perror("listen error\n");
		exit(1);
	}

	while (1)
	{
		connectd=accept(listend,(struct sockaddr*)&client,&len);	//等待客户端连接
		
		if (-1==connectd)
		{
			perror("create connect socket error\n");
			continue;
		}
		printf("connect  with %s:%d\n",inet_ntoa(client.sin_addr),htons(client.sin_port));

		int pid = fork();	//创建子进程
		if(pid == 0){	//如果是子进程
			close(listend);

			while(1){
					memset(send_buf,0,2048);
					memset(recv_buf,0,2048);
					
					recvnum = recv(connectd,recv_buf,sizeof(recv_buf),0);	//就收客户端发来的命令
					if (0>recvnum)
					{
						perror("recv error\n");
						close(connectd);
						break;
					}
					//处理客户端非正常退出的情况
					if (0==recvnum)
					{
						perror("the client quit abnormally\n");
						close(connectd);
						break;
					}
					
					recv_buf[recvnum]='\0';
					printf("client %s:%d >%s\n",inet_ntoa(client.sin_addr),htons(client.sin_port),recv_buf);

					if (0==strcmp(recv_buf,"quit"))
					{
						perror("the client quit\n");
						close(connectd);
						break;
					}

					//执行命令
					strcpy(cmd,"/bin/");
					strcat(cmd,recv_buf);
					execute(cmd,send_buf);

					if ('\0'==*send_buf)
					{
						memset(cmd,0,sizeof(cmd));
						strcpy(cmd,"/sbin/");
						strcat(cmd,recv_buf);
						execute(cmd,send_buf);
						
						if ('\0'==*send_buf)
						{	
							memset(cmd,0,sizeof(cmd));
							strcpy(cmd,"/usr/bin/");
							strcat(cmd,recv_buf);
							execute(cmd,send_buf);
						}
						
						if ('\0'==*send_buf)
						{	
							memset(cmd,0,sizeof(cmd));
							strcpy(cmd,"/usr/sbin/");
							strcat(cmd,recv_buf);
							execute(cmd,send_buf);
						}
					}
					if ('\0'==*send_buf)
					{
						sprintf(send_buf,"command is not vaild,check it please\n");
					}

					printf("%s\n",send_buf);
					if ( 0 >send(connectd,send_buf,sizeof(send_buf),0)) //向客户端发送消息
					{
						perror("send error\n");
						close(connectd);
						break;
					}
				}

				printf("disconnect with %s:%d\n",inet_ntoa(client.sin_addr),htons(client.sin_port));
				return 0;	//子进程返回
		}
	
		close(connectd);	//父进程关闭连接
   }

	close(listend);
	return 0;

}

//执行命令
int execute(char* command,char* buf)
{
	FILE * 	fp;
	int count;

	if (NULL==(fp = popen(command,"r")))
	{
		perror("creating pipe error\n");
		exit(1);
	}
	
	count = 0 ;

	while(((buf[count] = fgetc(fp))!=EOF)&&count<2047)
	count++;
	buf[count]='\0';

	pclose(fp);
	return count;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值