/*单进程并发服务器实例。该程序采用单进程并发服务器算法实现的。*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define PORT 1234           //服务器端口

#define BACKLOG 5           //listen队列中等待的连接数

#define MAXDATASIZE 1024 //缓冲区大小

typedef struct _CLIENT{        //客户端结构体

int       fd;        //客户端socket描述符

char*  name;

struct sockaddr_in addr;     //客户端地址信息结构体

char* data;

} CLIENT;

void process_cli(CLIENT *client, char* recvbuf, int len);  //客户请求处理函数

void savedata(char* recvbuf, int len, char* data);

main()

{

int    i, maxi, maxfd,sockfd;

int    nready;

ssize_t      n;

fd_set      rset, allset;    //select所需的文件描述符集合

int listenfd, connectfd;     //socket文件描述符

struct sockaddr_in server;     //服务器地址信息结构体

CLIENT client[FD_SETSIZE];     //FD_SETSIZE为select函数支持的最大描述符个数

char recvbuf[MAXDATASIZE];    //缓冲区

int sin_size;            //地址信息结构体大小

if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {    //调用socket创建用于监听客户端的socket

perror("Creating socket failed.");

exit(1);

}

int opt = SO_REUSEADDR;

setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));    //设置socket属性

bzero(&server,sizeof(server));

server.sin_family=AF_INET;

server.sin_port=htons(PORT);

server.sin_addr.s_addr = htonl (INADDR_ANY);

if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {    //调用bind绑定地址

perror("Bind error.");

exit(1);

}

if(listen(listenfd,BACKLOG) == -1){      //调用listen开始监听

perror("listen() error\n");

exit(1);

}

sin_size=sizeof(struct sockaddr_in);

//初始化select

maxfd = listenfd;

maxi = -1;

for (i = 0; i < FD_SETSIZE; i++) {

client[i].fd = -1;

}

FD_ZERO(&allset);        //清空

FD_SET(listenfd, &allset);    //将监听socket加入select检测的描述符集合

while(1)

{

struct sockaddr_in addr;

rset = allset;

nready = select(maxfd+1, &rset, NULL, NULL, NULL);    //调用select

printf("select saw rset actions and the readfset num is %d. \n",nready );

if (FD_ISSET(listenfd, &rset)) {      //检测是否有新客户端请求

printf("accept a connection.\n");

//调用accept,返回服务器与客户端连接的socket描述符

if ((connectfd = accept(listenfd,(struct sockaddr *)&addr,(socklen_t *)&sin_size))==-1) {

perror("accept() error\n");

continue;

}

//将新客户端的加入数组

for (i = 0; i < FD_SETSIZE; i++){

if (client[i].fd < 0) {

client[i].fd = connectfd;    //保存客户端描述符

client[i].name = new char[MAXDATASIZE];

client[i].addr = addr;

client[i].data = new char[MAXDATASIZE];

client[i].name[0] = '\0';

client[i].data[0] = '\0';

printf("You got a connection from %s.  ",inet_ntoa(client[i].addr.sin_addr) );

break;

}

}

printf("add new connect fd.\n");

if (i == FD_SETSIZE)

printf("too many clients\n");

FD_SET(connectfd, &allset);   //将新socket连接放入select监听集合

if (connectfd > maxfd)

maxfd = connectfd;   //确认maxfd是最大描述符

if (i > maxi)          //数组最大元素值

maxi = i;

if (--nready <= 0)

continue;      //如果没有新客户端连接,继续循环

}

for (i = 0; i <= maxi; i++) {

if ( (sockfd = client[i].fd) < 0)       //如果客户端描述符小于0,则没有客户端连接,检测下一个

continue;

if (FD_ISSET(sockfd, &rset)) {        //检测此客户端socket是否有数据

printf("recv occured for connect fd[%d].\n",i);

if ( (n = recv(sockfd, recvbuf, MAXDATASIZE,0)) == 0) { //从客户端socket读数据,等于0表示网络中断

close(sockfd);        //关闭socket连接

printf("Client( %s ) closed connection. User's data: %s\n",client[i].name,client[i].data);

FD_CLR(sockfd, &allset);    //从监听集合中删除此socket连接

client[i].fd = -1;        //数组元素设初始值,表示没客户端连接

delete client[i].name;

delete client[i].data;

} else

process_cli(&client[i], recvbuf, n);    //接收到客户数据,开始处理

if (--nready <= 0)

break;       //如果没有新客户端有数据,跳出for循环回到while循环

}

}

}

close(listenfd);  //关闭服务器监听socket

}

void process_cli(CLIENT *client, char* recvbuf, int len)

{

char sendbuf[MAXDATASIZE];

recvbuf[len-1] = '\0';

if (strlen(client->name) == 0) {

memcpy(client->name,recvbuf, len);

printf("Client's name is %s.\n",client->name);

return;

}

printf("Received client( %s ) message: %s\n",client->name, recvbuf);

savedata(recvbuf,len, client->data);

for (int i1 = 0; i1 < len - 1; i1++) {

sendbuf[i1] = recvbuf[len - i1 -2];

}

sendbuf[len - 1] = '\0';

send(client->fd,sendbuf,strlen(sendbuf),0);

}

void savedata(char* recvbuf, int len, char* data)

{

int start = strlen(data);

for (int i = 0; i < len; i++) {

data[start + i] = recvbuf[i];

}

}

linux多进程网络实例,Linux下一个单进程并发服务器的实例 使用select相关推荐

  1. 创建三个并发进程linux,Linux下几种并发服务器的实现模式(详解)

    1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发. 2>循环服务器和并发服务器 1.循 ...

  2. 1 linux下tcp并发服务器的几种设计的模式套路,Linux下几种并发服务器的实现模式(详解)...

    1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发. 2>循环服务器和并发服务器 1.循 ...

  3. linux网络编程(二)高并发服务器

    linux网络编程(二)高并发服务器 错误处理 高并发服务器 多进程并发服务器 客户端 错误处理 #include "wrap.h"int Bind(int fd, const s ...

  4. linux前一个的输出作为后一个参数,将Linux命令的结果作为下一个命令的参数

    查询所有的pid并杀死. jps -l | grep bdcsc2-native-demo | awk '{print $1}' | xargs kill -9 KISS:keep it short ...

  5. linux内核网络协议栈--linux bridge(十九)

    1 . 前言 本文是参考附录上的资料整理而成,以帮助读者更好的理解kernel中brdige 模块代码. 2. 网桥的原理 2.1 桥接的概念 简单来说,桥接就是把一台机器上的若干个网络接口" ...

  6. 浅析linux内核网络协议栈--linux bridge

    1 . 前言 本文是参考附录上的资料整理而成,以帮助读者更好的理解kernel中brdige 模块代码. 2. 网桥的原理 2.1 桥接的概念 简单来说,桥接就是把一台机器上的若干个网络接口" ...

  7. linux内核网络初始化,Linux内核--网络栈实现分析

    本文分析基于内核Linux Kernel 1.2.13 以后的系列博文将深入分析Linux内核的网络栈实现原理,这里看到曹桂平博士的分析后,也决定选择Linux内核1.2.13版本进行分析. 原因如下 ...

  8. linux内核网络协议栈--linux网络设备理解(十三)

    网络层次 linux网络设备驱动与字符设备和块设备有很大的不同. 字符设备和块设备对应/dev下的一个设备文件.而网络设备不存在这样的设备文件.网络设备使用套接字socket访问,虽然也使用read, ...

  9. linux 内核网络协议栈--linux内核路由机制(一)

    内核的路由部分是是网络中重要部分,目前在Linux内核中默认的路由查找算法使用的是Hash查找,所以你会看到很多的数据结构是XXX_hash什么之类(例如fn_hash).Linux内核从2.1开始就 ...

最新文章

  1. python环境变量值_如何在python中读取Windows环境变量值?
  2. mxnet转onnx
  3. pyton中的self具体含义,加self与不加self有什么区别?
  4. 军规22 充分使用持续集成和持续部署
  5. Solr实战(二):索引操作
  6. C++变量的初始化问题及列表初始化
  7. 应用数学软件测试题,高等数学第六章定积分应用综合测试题
  8. 《走出软件作坊》读后感
  9. linux文件名快速键入,linux修改文件名【使用模式】
  10. 只卖男人,年赚5.6亿!全网最火“爱情骗子”,被戳穿了
  11. 谈谈API接口安全性设计思路
  12. mahout AbstractJDBCModel log
  13. 查看npy文件中存的是什么
  14. 如何做网络投票的刷票外挂(二)
  15. Yingye Zhu‘s Luogu Background
  16. 神话情话(神雕侠侣主题曲)铃声 神话情话(神雕侠侣主题曲)手机...
  17. Tic-Tac-Toe:基于Minimax算法的人机对弈程序(python实现)
  18. JavaFx教程-01初识javaFX
  19. 2020微信对话截图一件生成神器
  20. Python基础——魔法方法(二)

热门文章

  1. LOJ#6044. 「雅礼集训 2017 Day8」共(Prufer序列)
  2. 同一台服务器,mysql登录不了指定端口的问题
  3. (WPF, MVVM) Event 处理
  4. 理解C++ lvalue与rvalue
  5. java中一些入门级技巧
  6. 快给你的app上锁吧(android图案解锁)
  7. Xfire方式开发和解析webservice
  8. dojo Quick Start/dojo入门手册--package机制
  9. 威联通装linux百度网盘,威联通NAS使用百度云Docker教程,超简单!
  10. linux who命令实现,linux下 who命令(3)(示例代码)