修改远程控制服务器代码,使得服务器同时能够向多个用户提供服务。
消除僵尸进程,收回所有子进程资源。
了解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
#include
#include
#include
#include
#include
#include
#include
#include
# include
# include
#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;
}