高并发服务器

高并发服务器

并发服务器开发

1.多进程并发服务器   使用多进程并发服务器时要考虑以下几点:

  • 父最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符)
  • 系统内创建进程个数(内存大小相关)
  • 进程创建过多是否降低整体服务性能(进程调度)

server

/* server.c */
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include "wrap.h"
#define MAXLINE 80
#define SERV_PORT 8000 void do_sigchild(int num)
{
waitpid(0, NULL, WNOHANG);
}
int main(void)
{
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
int listenfd, connfd;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
int i, n;
pid_t pid;
struct sigaction newact;
newact.sa_handler = do_sigchild;
sigemptyset(&newact.sa_mask);
newact.sa_flags = 0;
sigaction(SIGCHLD, &newact, NULL);
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
Listen(listenfd, 20);
printf("Accepting connections ...\n");
while (1) {
cliaddr_len = sizeof(cliaddr);
connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
//多进程服务器
pid = fork();
if (pid == 0) {
//子进程
Close(listenfd);
while (1) {//可以循环读
n = Read(connfd, buf, MAXLINE);
if (n == 0) {
printf("the other side has been closed.\n");
break;
}
printf("received from %s at PORT %d\n",
inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
ntohs(cliaddr.sin_port));
for (i = 0; i < n; i++)
buf[i] = toupper(buf[i]);
Write(connfd, buf, n);
}
Close(connfd);//若不关长期以往会导致文见文件描述符关闭
return 0;
}
else if (pid > 0) {
Close(connfd);
}
else
perr_exit("fork");
}
}

client

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include "wrap.h"
#define MAXLINE 80
#define SERV_PORT 8000
int main(int argc, char *argv[])
{
struct sockaddr_in servaddr;
char buf[MAXLINE];
int sockfd, n;
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT);
Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
while (fgets(buf, MAXLINE, stdin) != NULL) {
Write(sockfd, buf, strlen(buf));
n = Read(sockfd, buf, MAXLINE);
if (n == 0)
printf("the other side has been closed.\n");
else
Write(STDOUT_FILENO, buf, n);
}
Close(sockfd);
return 0;
}

2.多线程并发服务器   在使用线程模型开发服务器时需考虑以下问题:

  • 调整进程内最大文件描述符上限
  • 线程如有共享数据,考虑线程同步
  • 服务于客户端线程退出时,退出处理。(退出值,分离态)
  • 系统负载,随着链接客户端增加,导致其它线程不能及时得到CPU

多线程

server

/* server.c */
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "wrap.h"
#define MAXLINE 80
#define SERV_PORT 8000
struct s_info {
struct sockaddr_in cliaddr;
int connfd;
};
void *do_work(void *arg)
{
int n, i;
struct s_info *ts = (struct s_info*)arg;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
/* 可以在创建线程前设置线程创建属性,设为分离态,哪种效率高内? */
pthread_detach(pthread_self());
while (1) {
n = Read(ts->connfd, buf, MAXLINE);
if (n == 0) {
printf("the other side has been closed.\n");
break;
}
printf("received from %s at PORT %d\n",
inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr, str, sizeof(str)),
ntohs((*ts).cliaddr.sin_port));
for (i = 0; i < n; i++)
buf[i] = toupper(buf[i]);
Write(ts->connfd, buf, n);
}
Close(ts->connfd);
}
int main(void)
{
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
int listenfd, connfd;
int i = 0;
pthread_t tid;
struct s_info ts[383];
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
Listen(listenfd, 20);
printf("Accepting connections ...\n");
while (1) {
cliaddr_len = sizeof(cliaddr);
connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
ts[i].cliaddr = cliaddr;
ts[i].connfd = connfd;
/* 达到线程最大数时,pthread_create出错处理, 增加服务器稳定性 */
pthread_create(&tid, NULL, do_work, (void*)&ts[i]);
i++;
}
return 0;
}

client

/* client.c */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include "wrap.h"
#define MAXLINE 80
#define SERV_PORT 8000
int main(int argc, char *argv[])
{
struct sockaddr_in servaddr;
char buf[MAXLINE];
int sockfd, n;
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT);
Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));while (fgets(buf, MAXLINE, stdin) != NULL) {
Write(sockfd, buf, strlen(buf));
n = Read(sockfd, buf, MAXLINE);
if (n == 0)
printf("the other side has been closed.\n");
else
Write(STDOUT_FILENO, buf, n);
}
Close(sockfd);
return 0;
}
来源https://www.cnblogs.com/rainbow1122/p/7875702.html

linux学习之多高并发服务器篇(一)的更多相关文章

  1. linux学习之多高并发服务器篇(三)

    UDP多播服务器 多播 组播组可以是永久的也可以是临时的.组播组地址中,有一部分由官方分配的,称为永久组播组.永久组播组保持不变的是它的ip地址,组中的成员构成可以发 生变化.永久组播组中成员的数量都 ...

  2. linux学习之高并发服务器篇(二)

    高并发服务器 1.线程池并发服务器 两种模型: 预先创建阻塞于accept多线程,使用互斥锁上锁保护accept(减少了每次创建线程的开销) 预先创建多线程,由主线程调用accept 线程池 3.多路 ...

  3. Linux + C + Epoll实现高并发服务器(线程池 + 数据库连接池)(转)

    转自:http://blog.csdn.net/wuyuxing24/article/details/48758927 一, 背景 先说下我要实现的功能,server端一直在linux平台下面跑,当客 ...

  4. PHP写的异步高并发服务器,基于libevent

    PHP写的异步高并发服务器,基于libevent 博客分类: PHP PHPFPSocketLinuxQQ  本文章于2013年11月修改. swoole已使用C重写作为PHP扩展来运行.项目地址:h ...

  5. JAVA NIO non-blocking模式实现高并发服务器(转)

    原文链接:JAVA NIO non-blocking模式实现高并发服务器 Java自1.4以后,加入了新IO特性,NIO. 号称new IO. NIO带来了non-blocking特性. 这篇文章主要 ...

  6. 高并发服务器建议调小 TCP 协议的 time_wait 超时时间。

    1. [推荐]高并发服务器建议调小 TCP 协议的 time_wait 超时时间. 说明:操作系统默认 240 秒后,才会关闭处于 time_wait 状态的连接,在高并发访问下,服 务器端会因为处于 ...

  7. JAVA NIO non-blocking模式实现高并发服务器

    JAVA NIO non-blocking模式实现高并发服务器 分类: JAVA NIO2014-04-14 11:12 1912人阅读 评论(0) 收藏 举报 目录(?)[+] Java自1.4以后 ...

  8. 为一个支持GPRS的硬件设备搭建一台高并发服务器用什么开发比较容易?

    高并发服务器开发,硬件socket发送数据至服务器,服务器对数据进行判断,需要实现心跳以保持长连接. 同时还要接收另外一台服务器的消支付成功消息,接收到消息后控制硬件执行操作. 查了一些资料,java ...

  9. 第15章 高并发服务器编程(2)_I/O多路复用

    3. I/O多路复用:select函数 3.1 I/O多路复用简介 (1)通信领域的时分多路复用 (2)I/O多路复用(I/O multiplexing) ①同一线程,通过“拨开关”方式,来同时处理多 ...

随机推荐

  1. 用latex写简历

    最近终于逐渐掌握了用Latex写中文简历的问题.首先就是必须基于交大前辈bin yuan的模板进行学习. 如果有了一般论文撰写和Beamer做PPT的经验,不难发现resume的模板也是遵循一套程式的 ...

  2. jQuery学习(八)——使用JQ插件validation进行表单校验

    1.官网下载:http://bassistance.de/jquery-plugins/jquery-plugin-validation/ 目录结构: 2.引入jquery库和validation插件 ...

  3. JavaScript学习——使用JS完成注册页面表单校验

    1.步骤分析 第一步:确定事件(onsubmit)并为其绑定一个函数 第二步:书写这个函数(获取用户输入的数据<获取数据时需要在指定位置定义一个 id>) 第三步:对用户输入的数据进行判断 ...

  4. sharding-jdbc,轻量级数据库分库分表中间件

    Sharding-JDBC是当当应用框架ddframe中,从关系型数据库模块dd-rdb中分离出来的数据库水平分片框架,实现透明化数据库分库分表访问.Sharding-JDBC是继dubbox和ela ...

  5. SQL之子查询

    子查询概念:把一个查询的结果在另一个查询中使用就叫做子查询 1.子查询作为条件时 当我们使用子查询作为条件时,若子查询返回值为多个,则会报以下错误: "子查询返回的值不止一个.当子查询跟随在 ...

  6. 优动漫PAINT个人版绘制树叶教程

    超详细树叶绘制法,更有配套绘树小TIPE!让你画树So Easy~一秒变身,画树达人! 优动漫PAINT个人版软件下载:http://www.dongmansoft.com/chanpin.html ...

  7. 优动漫PAINT-超简单灌木教程

    超简单灌木教程~零基础神马的都能神还原哦! 优动漫PAINT下载:http://wm.makeding.com/iclk/?zoneid=18597 想要Get到更多有关优动漫的信息包括软件下载,可关 ...

  8. [NOI2015]品酒大会(后缀树+DP)

    后缀自动机有一个性质. 就是如果倒建SAM两个串的lcp就是这两个串的结束节点的LCA. 然后就可以愉快的跑DP了. 对于每一个后缀树上的节点\(u\),它对\(len[u]\)的贡献是\(\sum_ ...

  9. luogu P1405 苦恼的小明(欧拉定理)

    题意 求a1^a2^a3^...^an(mod10007)n<=1000000,a[i]<=10000 题解 明眼人一眼就可以看出是欧拉定理的推论. 首先这个题是错的,没说保证互质. 然而 ...

  10. C++ Primer笔记13_运算符重载_总结

    总结: 1.不能重载的运算符: . 和 .* 和 ?: 和 ::  和 sizeof 和 typeid 2.重载运算符有两种基本选择: 类的成员函数或者友元函数, 建议规则例如以下: 运算符 建议使用 ...