// File:singlethread-mult-tcp-server.C
/*单线程并发服务器实例。该程序采用单线程并发服务器算法实现的。*/
#include <stdio.h> /* These are the usual header files */
#include <string.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <stdlib.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 5 /* Number of allowed connections simutaniously*/
#define MAXDATASIZE 1000
typedef struct _CLIENT{
int fd;
char* name;
struct sockaddr_in addr; /* client's address information */
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;
int listenfd, connectfd; /* socket descriptors */
struct sockaddr_in server; /* server's address information */
/* client's information */
CLIENT client[FD_SETSIZE];
char recvbuf[MAXDATASIZE];
int sin_size;
/* Create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
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) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error/n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
/*initialize for select */
maxfd = listenfd;
maxi = -1;
for (i = 0; i < FD_SETSIZE; i++) {
client[i].fd = -1;
}
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
while(1)
{
struct sockaddr_in addr;
rset = allset;
nready = select(maxfd+1, &rset, NULL, NULL, NULL);
printf("select saw rset actions and the readfset num is %d. /n",nready );
if (FD_ISSET(listenfd, &rset))
{ /* new client connection */
/* Accept connection */
printf("accept a connection./n");
if ((connectfd = accept(listenfd,(struct sockaddr *)&addr,(socklen_t *)&sin_size))==-1) {
perror("accept() error/n");
continue;
}
/* Put new fd to client */
for (i = 0; i < FD_SETSIZE; i++)
if (client[i].fd < 0) {
client[i].fd = connectfd; /* save descriptor */
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); /* add new descriptor to set */
if (connectfd > maxfd) maxfd = connectfd;
if (i > maxi) maxi = i;
if (--nready <= 0) continue; /* no more readable descriptors */
}
for (i = 0; i <= maxi; i++)
{
/* check all clients for data */
if ( (sockfd = client[i].fd) < 0) continue; /* no more connected clients*/
if (FD_ISSET(sockfd, &rset)) {
printf("recv occured for connect fd[%d]./n",i);
if ( (n = recv(sockfd, recvbuf, MAXDATASIZE,0)) == 0) {
/*connection closed by client */
close(sockfd);
printf("Client( %s ) closed connection. User's data: %s/n",client[i].name,client[i].data);
FD_CLR(sockfd, &allset);
client[i].fd = -1;
delete client[i].name;
delete client[i].data;
} else
process_cli(&client[i], recvbuf, n);
if (--nready <= 0) break; /* no more readable descriptors */
}
}
}
close(listenfd); /* close listenfd */
}
void process_cli(CLIENT *client, char* recvbuf, int len)
{
char sendbuf[MAXDATASIZE];
recvbuf[len-1] = '/0';
if (strlen(client->name) == 0) {
/* Got client's name from client */
memcpy(client->name,recvbuf, len);
printf("Client's name is %s./n",client->name);
return;
}
/* save client's data */
printf("Received client( %s ) message: %s/n",client->name, recvbuf);
/* save user's data */
savedata(recvbuf,len, client->data);
/* reverse usr's 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];
}
}
|
相关推荐
王健伟老师(51CTO或者其他平台)的课程,学习辅助资料,帮助理解 (已更新,看资源的下一版本)
18.5 服务器设计 439 18.6 服务器源码 439 18.7 客户机设计 463 18.7.1 终端行规程 463 18.7.2 一个进程还是两个进程 464 18.8 客户机源码 465 18.9 小结 474 习题 474 第19章 伪终端 476 19.1 引言 476 19.2 概述 ...
1. 算法与设计模式专栏 2. 后台组件编程专栏 3. 基础组件开发专栏 4. 开源框架 5. 网络服务 6. 性能测试 7. 代码工程化 8. 互联网云盘项目 高级架构 1. 源码分析 2. 中间件开发 3. Linux内核 4.集群 零声c++资料 ......
18.5 服务器设计 439 18.6 服务器源码 439 18.7 客户机设计 463 18.7.1 终端行规程 463 18.7.2 一个进程还是两个进程 464 18.8 客户机源码 465 18.9 小结 474 习题 474 第19章 伪终端 476 19.1 引言 476 19.2 概述 ...
《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...
18.5 服务器设计 439 18.6 服务器源码 439 18.7 客户机设计 463 18.7.1 终端行规程 463 18.7.2 一个进程还是两个进程 464 18.8 客户机源码 465 18.9 小结 474 习题 474 第19章 伪终端 476 19.1 引言 476 19.2 概述 ...
18.5 服务器设计 439 18.6 服务器源码 439 18.7 客户机设计 463 18.7.1 终端行规程 463 18.7.2 一个进程还是两个进程 464 18.8 客户机源码 465 18.9 小结 474 习题 474 第19章 伪终端 476 19.1 引言 476 19.2 概述 ...
群聊模式采用C-S-C模式,即客户端发送信息给服务端,服务端进行处理返回给其他客户端。设计模式为服务器多进程响应登录、注册,单进程并发客户聊天操作,客户端多线程响应服务端反馈。
UNIX环境高级编程_第2版 ----------------------------------------------------------- 共两个压缩包( UNIX环境高级编程_第2版.part1 UNIX环境高级编程_第2版.part1 ) ------------------------------------------...
第2 章Linux编程环境....................................................................................................14 2.1 Linux环境下的编辑器................................................. 14 ...
2. 客户端/服务器架构:客户端/服务器架构是一种常用的软件架构模式,在本系统中,客户端基于嵌入式Linux系统,服务器端采用Python和PyQt开发,实现了跨平台运行和多线程技术。 3. 多线程技术:多线程技术是一种...
-国嵌应用班-7-5(并发服务器).avi -国嵌应用班-7-6(必修实验).avi 国嵌视频3.iso -国嵌课程3-ARM系统进阶班 -第1天(ARM系统开发基础) -ARM系统精讲班-1-1(ADS集成开发环境).avi -ARM系统精讲班-1-2(ARM...
基于go语言,学习和编写基本的设计模式demoGo语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统...
UNIX环境高级编程_第2版 ----------------------------------------------------------- 共两个压缩包( UNIX环境高级编程_第2版.part1 UNIX环境高级编程_第2版.part1 ) ------------------------------------------...
基于 Socket 网络通讯技术,使用Qt5进行GUI编程,结合OpenCV图像处理,采用Sqlite3数据库,实现的 360 度智能...项目核心技术点 :服务器分离、共享内存设计、线程池、Socket网络编程、进程间通信、epoll多路IO复用等。
-国嵌应用班-7-5(并发服务器).avi -国嵌应用班-7-6(必修实验).avi 国嵌视频3.iso -国嵌课程3-ARM系统进阶班 -第1天(ARM系统开发基础) -ARM系统精讲班-1-1(ADS集成开发环境).avi -ARM系统精讲班-1-2(ARM工作...
包含了多个模块的面试题讲解,如:Redis、MySQL、框架、微服务、消息中间件、数据结构、Java集合源码分析、多线程、JVM、设计模式、高并发场景、企业实际问题场景等等各个方面逐一讲解。 1、具备扎实的编程基础,...
分布式系统框架 一。项目简介 这是基于Linux平台C ++编写的分布式系统框架,非常适合Linux某些项目有需求的同学...但是这样存在的问题是服务器当并发量大到一定的程度时,由于压力太大,出现对客户端响应过慢的情况,