1. 编译server、tcpclient并启动

gcc -o server server.c
gcc -o tcpclient tcpclient.c

2.在三个客户端分别输入测试命令

ls
whoami
pwd

3. 通过查看网络状态,客户端是否为多进程实现并发服务器

netstat-anp | grep 8900

发现8900端口的进程有三个不同的pid号,说明启动的三个客户端是三个不同的进程,实现了并发服务器。

4. 测试僵尸进程

  • 先关闭一个客户端进程
  • 输入命令查看僵尸进程
  • 发现僵尸进程的pid不是我的进程的pid号
  • 可见程序已经自动清除僵尸进程

源码

server.c

#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<string.h>
#include<netdb.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define PORT 8900
#define BUF_SIZE 2048int execute(char* command,char* buf);int main()
{int sockfd;struct sockaddr_in client;struct sockaddr_in server;char send_buf[BUF_SIZE];char recv_buf[BUF_SIZE];char cmd[2048];int sendnum;int recvnum;int length;int port;int connected;   //changememset(send_buf,0,2048);memset(recv_buf,0,2048);memset(cmd,0,2048);  //changeport = PORT;if (-1==(sockfd=socket(AF_INET,SOCK_STREAM,0)))  //change{perror("generating socket error\n");exit(1);}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(sockfd,(struct sockaddr*)&server,sizeof(struct sockaddr))){perror("binding error\n");close(sockfd);exit(1);}if(-1==listen(sockfd,10)){perror("listen socket error\n");close(sockfd);return -1;}length = sizeof(struct sockaddr_in);while(1){memset(recv_buf,0,2048);memset(send_buf,0,2048);if(-1==(connected=accept(sockfd,(struct sockaddr*)&client,&length))){perror("three shakehands error\n");close(sockfd);return -1;}//change///int pid = fork();if((pid=fork())<0){printf("fork failed\n");_exit(1);}else if(pid == 0){//close(connected);process(connected, client);}else{close(connected);continue;}close(connected);}close(sockfd);exit(1);
}int process(int connected, struct sockaddr_in client)
{char sendbuf[BUF_SIZE];char recvbuf[BUF_SIZE];int sendnum = 0;int recvnum = 0;int cnt;int n, fd[2];int length = sizeof(struct sockaddr_in);char cmd[10];char path[2048];pid_t pid;memset(sendbuf, 0, BUF_SIZE);memset(recvbuf, 0, BUF_SIZE);if(pipe(fd)<0)printf("creat pipe error \n");while(1){if(0>=(recvnum=recv(connected, recvbuf, BUF_SIZE, 0))){perror("recv error\n");close(connected);return -1;}recvbuf[recvnum]='\0';fprintf(stderr, "the command is:%s\n", recvbuf);if(0==strcmp(recvbuf, "quit")){perror("quitting remote controling\n");close(connected);return 0;    }strcpy(cmd,"/bin/");strcat(cmd,recvbuf);execute(cmd,sendbuf);if ('\0'==*sendbuf){memset(cmd,0,sizeof(cmd));strcpy(cmd,"/sbin/");strcat(cmd,recvbuf);execute(cmd,sendbuf);if ('\0'==*sendbuf){       memset(cmd,0,sizeof(cmd));strcpy(cmd,"/usr/bin/");strcat(cmd,recvbuf);execute(cmd,sendbuf);}if ('\0'==*sendbuf){       memset(cmd,0,sizeof(cmd));strcpy(cmd,"/usr/sbin/");strcat(cmd,recvbuf);execute(cmd,sendbuf);}}if ('\0'==*sendbuf)sprintf(sendbuf,"command is not vaild,check it please\n");printf("%s\n",sendbuf);sendnum = send(connected,sendbuf,sizeof(sendbuf),0);if (0>sendnum){perror("sending data error\n");continue;}}
}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);if(0==count)   //changeprintf(buf, "%s cannot execute\n",command);return count;
}

tcpclient.c

#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<string.h>
#include<netdb.h>
#include<netinet/in.h>
#include<arpa/inet.h>#define PORT 8900
#define BUF_SIZE 2048void print_usage(char* str)
{printf("%s usage :\n",str);printf("%s Ipaddr \n");
}
int main(int argc, char** argv)
{int sockfd;struct sockaddr_in client;struct sockaddr_in server;char send_buf[BUF_SIZE];char recv_buf[BUF_SIZE];  int sendnum;int recvnum;int length;int port;if(2!=argc){print_usage(argv[0]);exit(1);    }memset(send_buf,0,2048);memset(recv_buf,0,2048);port = PORT;if (-1==(sockfd=socket(AF_INET,SOCK_STREAM,0)))  // change{perror("generating socket error\n");exit(1);} memset(&server,0,sizeof(struct sockaddr_in));    //changeserver.sin_family = AF_INET;server.sin_addr.s_addr = inet_addr(argv[1]);server.sin_port = htons(port);if(-1==connect(sockfd, (struct sockaddr*)&server, sizeof(server)))  //change{perror("connect error\n");close(sockfd);return -1;}while(1){memset(send_buf,0,2048);memset(recv_buf,0,2048);printf("tcp>");   //changegets(send_buf);  //change   Don't use 'fgets'!!!!!!!!!!!!printf("\n");if (0>send(sockfd,send_buf,strlen(send_buf),0))  //change{perror("error occar in sending data\n");break;}if (0==strcmp(send_buf,"quit")){printf("quit...\n");     //changebreak;}length = sizeof(struct sockaddr);recvnum = recv(sockfd,recv_buf,2048,0);if(0<recvnum)                          //change{recv_buf[recvnum]='\0';printf("%s\n",recv_buf);}else{continue;}//printf("%s\n",recv_buf);}close(sockfd);exit(1);
}

tcpserver.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<unistd.h>
#define PORT 8900
#define BUFSIZE 2048void processchild(int clientsoket);FILE *mypopen(char *cmd, char type)
{int pipefd[2];int pid_t;if(type!='r'&&type!='w'){printf("myopen() flag error/n");return NULL;}if(pipe(pipefd)<0){printf("myopen() pipe create error/n");return NULL;}pid_t=fork();if(pid_t<0)return NULL;if(0==pid_t){if(type=='r'){close(pipefd[0]);dup2(pipefd[1],STDOUT_FILENO);close(pipefd[1]);}else{close(pipefd[1]);dup2(pipefd[0],STDIN_FILENO);close(pipefd[0]);}char *argv[]={cmd,NULL};if(execvp(cmd,argv)<0)return NULL;}wait(0);if(type=='r'){close(pipefd[1]);return fdopen(pipefd[0],"r");}else{close(pipefd[0]);return fdopen(pipefd[1],"w");}
}int execute(char*command,char*buf)
{FILE *fp;int count;char commandbuf[2056];if((NULL==command)||(NULL==buf)){perror("command or buf is empty\n");return -1;}count=0;memset(commandbuf,0,2056);strcat(commandbuf,"sh -c ");strcat(commandbuf,command);fprintf(stderr,"the command is %s\n",commandbuf);char ar='r';if(NULL==(fp=mypopen(commandbuf,ar))){perror("create pipe error\n");return -1;}while((count<2047)&&(EOF!=(buf[count++]=fgetc(fp))));buf[count-1]='\0';return count;
}int main()
{int sockfd;struct sockaddr_in client;struct sockaddr_in server;int opt;int cnt;int addr_len=sizeof(client);/* The first stage:INITILIZE  */memset(&client,0,sizeof(client));memset(&server,0,sizeof(server));sockfd=-1;opt=SO_REUSEADDR;/*The second stage:create listen socket  */if(-1==(sockfd=socket(AF_INET,SOCK_STREAM,0))){perror("create socket error\n");return -1;}setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));/* The third stage:bind socket */server.sin_family=AF_INET;server.sin_addr.s_addr=htonl(INADDR_ANY);server.sin_port=htons(PORT);if(-1==bind(sockfd,(struct sockaddr*)&server,sizeof(server))){perror("bind socket error\n");close(sockfd);return -1;}if(listen(sockfd,5)<0){perror("listen socket error\n");exit(1);}/* The fifth stage:creat connect socket */while(1){int clientsocket;clientsocket=accept(sockfd,(struct sockaddr*)&client,(socklen_t*)&addr_len);if(clientsocket<0){perror("error:accept client socket!!\n");continue;}int pid=fork();if(pid>0){close(clientsocket);continue;}else if(pid==0){close(sockfd);processchild(clientsocket);exit(0);}else{printf("error: fork child process!!");}}close(sockfd);
}void processchild(int clientsocket)
{char buffer[BUFSIZE];int iDatanum;int cnt;char sendbuf[BUFSIZE];int sendnum;while(1){iDatanum=recv(clientsocket,buffer,BUFSIZE,0);if(0>iDatanum){perror("error: Recv data!!");exit(0);}buffer[iDatanum]='\0';fprintf(stderr,"the command is:%s\n",buffer);if(0==strcmp(buffer,"quit")){fprintf(stderr,"the client is quit\n");close(clientsocket);exit(0);}if(1>=(cnt=execute(buffer,sendbuf))){sprintf(sendbuf,"the invalid command,please try again\n");}fprintf(stderr,"the result is \n%s",sendbuf);if(0>=(sendnum=write(clientsocket,sendbuf,strlen(sendbuf)))){perror("the commucation error\n");close(clientsocket);exit(0);}}close(clientsocket);
}

【c语言】4 并发服务器相关推荐

  1. C语言 TCP并发服务器

    友链 gcc 1.c -o 1 -lpthread gcc 2.c -o 2 -lpthread 服务端 // ..使用内存映射可以拷贝文件 /* 对原始文件进行内存映射 创建一个新文件 把新文件的数 ...

  2. 如何使用 Go 语言搭建企业级高并发服务器?

    每到节假日和过年,需要外出通行的人几乎都会遇到一个问题:抢火车票!当全国上亿人都在固定的时间段抢票,服务器动辄就要承受上百万级并发的情况时,你就会明白,一个支持高并发的服务器架构有多重要! 在后端程序 ...

  3. Unix C语言编写基于IO多路复用的小型并发服务器

    背景介绍 如果服务器要同时处理网络上的套接字连接请求和本地的标准输入命令请求,那么如果我们使用accept来接受连接请求,则无法处理标准输入请求;类似地,如果在read中等待一个输入请求,则无法处理网 ...

  4. linux C语言TCP协议实现镜像服务器,并发服务器,文件传输

    镜像服务器 返回连接者的ip端口回去: #include <stdio.h> #include <sys/types.h> /* See NOTES */ #include & ...

  5. 网络编程-C语言实现多进程并发服务器

    在Linux操作系统下,服务器通过fork()复制已调用的进程来创建子进程,以此来实现多进程并发服务器 功能:客户端发送任意字符串,服务器端将字符串小写转大写toupper();并返回给客户端,客户端 ...

  6. uban服务器系统,Web服务器-并发服务器-Epoll(3.4.5)

    @ 1.介绍 epoll是一种解决方案,nginx就是用的这个 中心思想:不要再使用多进程,多线程了,使用单进程,单线程去实现并发 在上面博客实现的代码中使用过的轮询去查看套接字有没有数据,而epol ...

  7. Linux 高并发服务器开发

    该文章是通过观看牛客网的视频整理所得,以及在实践过程中遇到的问题及解决方案的整理总结. Linux 高并发服务器开发 linux 系统编程 linux 环境的搭建 环境搭建需要的软件 虚拟机中安装 u ...

  8. Linux高并发服务器开发---笔记1(环境搭建、系统编程、多进程)

    0613 第4章 项目制作与技能提升 4.0 视频课链接 4.1 项目介绍与环境搭建 4.1.1 项目介绍 4.1.2 开发环境搭建 ①安装Linux系统.XSHELL.XFTP.Visual Stu ...

  9. Linux 高并发服务器实战 - 2 Linux多进程开发

    Linux 高并发服务器实战 - 2 Linux多进程开发 进程概述 概念1: 概念2: 微观而言,单CPU任意时刻只能运行一个程序 并发:两个队列交替使用一台咖啡机 并行:两个队列同时使用两台咖啡机 ...

最新文章

  1. bzoj 2730: [HNOI2012]矿场搭建——tarjan求点双
  2. 《微软的软件测试之道》(How We Test Software at Microsoft)
  3. Nginx 作为web server 的优化要点
  4. 手动设计简单的Token验证
  5. SDL2 自建对话框
  6. win10开机密码忘记了的解锁教程
  7. fun函数python_Python函数
  8. 2017百度之星资格赛:1001. 度度熊保护村庄(floyd最小环)
  9. python的copy模块是哪个模块_每周一个 Python 模块 | copy
  10. flashback query闪回数据
  11. Makefile的入门完整教程(包学包会)
  12. 产业互联网周报:中国移动:择时分拆业务上市;金山云CEO王育林辞职;谷歌负面缠身,数据中心爆炸又遭罚款...
  13. 24V电磁铁电磁特模块电路分析
  14. 第三周《java语言程序设计——面向对象入门》学习总结
  15. 1000张动漫萌妹子次元系人物素材图,可做壁纸头像
  16. 卡内基梅隆大学(CMU)的Eric Xing(邢波)教授为什么能读完一般学校的分子生物学PhD后到伯克利去CS PhD?
  17. SpringBoot JPA(JpaRepository)动态查询 分页展示
  18. VS2010中VB.NET中API函数的调用
  19. java soaoffice_很不错的在线Office控件:IWebOffice与SOAOffice
  20. 2021-2027全球与中国接触角测量仪市场现状及未来发展趋势

热门文章

  1. XQuartz安装与使用
  2. 移动应用开发测试工具Bugtags集成和使用教程【转载】
  3. 学计算机的闷骚,当一个“闷骚”是一种怎样的体验?-心理学文章-壹心理
  4. 欧姆龙PLC modbusRTU通讯解析(CP1E)
  5. 对于Adobe平面设计证书,高级平面设计师,有话说!
  6. android局域网通信方案,Android基于TCP的局域网聊天通信
  7. c语言right,C++ left和right操作符用法详解
  8. arduino处理中频信号_接收机的中频处理技术
  9. 通过meta代码强制浏览器使用WebKit内核极速模式(解决 meta name=renderer content=webkit 不起作用)
  10. 视频文件大小码率计算方法