当前位置:  互联网>综合
本页文章导读:
    ▪写一个后台服务器--引子      最近去了几家公司面试,有一些大公司(比如企鹅)的考核内容真心弱智,考的都是些算法,尼玛,拿一个刚毕业的学生来做说不定也可以过的,看来本来就不是在招搞服务器的,举个例.........
    ▪搭建一个后台服务器--客户端      上篇规定的协议请求部分: request: username/password, 约定username与password  各占32个字节(联同末位0) 可以将客户端的逻辑设计成: 1.将username,password  封装进buffer 2.连接服务端 3.发送buf.........
    ▪搭建一个后台服务器--服务端(异步,大并发)      上篇的阻塞模式下服务器的并发只有几K,而真正的server 像nginx, apache, yumeiz 轻轻松松处理几万个并发完全不在话下,因此大并发的场合下是不能用阻塞的。 1W的并发是一个分隔点,如果单进程.........

[1]写一个后台服务器--引子
    来源: 互联网  发布时间: 2013-10-19

最近去了几家公司面试,有一些大公司(比如企鹅)的考核内容真心弱智,考的都是些算法,尼玛,拿一个刚毕业的学生来做说不定也可以过的,看来本来就不是在招搞服务器的,举个例子,企鹅多个部门都曾出的一道题:如何知道集合A,B中的相关性。

意思就是哪些元素在A,B之中都有,哪些元素在A,B中不都出现。

其实解法很简单,学过算法的完全可以做到 。我们知道集合具有互异性,就是集合中的元素只能出现一次,可以建一个map< key, value >,是标准库的还是自建一个红黑树都无所谓,

将A,B集合中的元素当成key,各自遍历一次,插入map中,每次插入 value自增一次,最后再遍历一次map,所有 value = 2的key是A,B共有的,value=1的key是A,B相异的。

如果A,B中的元素是整数,而且很小,问题则退化成类似计数排序,解法如下:

#define MAX_NUM

A{ 2,4,6,10,7,25 } B{ 3,9,4,2,19,25 }

int test( int A[], int a_len, int B[], int b_len )

{

int size, i, max, tp_key;

int  *tmp;

if( !a_len || !b_len )

{

return -1;

}

size = MAX_NUM * sizeof( int );

tmp = malloc( size );

if( !tmp )

{

return -1;

}

memset( tmp, 0, size );

max = 0;

for( i = 0; i < a_len; ++i )

{

tp_key = A[i];

max = tp_key > max ? tp_key : max;

tmp[ tp_key ]++;

}

for( i = 0; i < b_len; ++i )

{

tp_key = B[i];

max = tp_key > max ? tp_key : max;

tmp[ tp_key ] ++;

}

++max;

for( i = 0; i < max; ++i )

{

if( !tmp[ i ] )

continue;

if( 1 == tmp[ i ]  )

{

printf( "%d is in A or B\n", i );

}

else

{

printf( "%d is in A and B\n", i );

}

}

free( tmp );

return 0;

}

言归正传,其实算法应该是大家的基本功,考核算法应该也没有错,但既然招的是服务器架构开发,我想考核更多的是实战经验。

有一家中等公司的面试题不错,此系列博文将围绕它展开研究。

原题:时间同步系统开发需求

需求场景:客户端向服务器发起登录请求,鉴权通过后(为了简化工作,所有登录请求,只要请求参数里的用户名和密码不为空,都鉴权通过),客户端再向服务器请求当前系统时间,服务器返回当前系统时间后关闭连接。


要求:

1、传输层使用TCP协议,应用层协议不限。

2、可支持同时在线用户量:大于 2W。

3、并发性能:没有明确指标。

4、服务器端运行环境:linux 2.4以上内核版本;开发语言:C++/C。

5、客户端运行环境:不限;开发语言:不限。(可以很简单,不要求界面)

6、要求有模拟性能测试操作方法,如多客户端、多线程模拟同时请求等。

7、用真实代码。

8、不要求日志系统,但是要考虑在主线程打印屏幕引起的性能问题。


我就觉得要是哪个公司面试的时候能出得出这样的题目,那就应该很专业了,对面试的人也就可以算得上挑战了。

tcp 服务端-客户端通信的程序,网上一搜一大堆,大家可能都会写,但是并发量和容错性不一定能上得去,2W的并发量不是盖出来的,如果这道题目能够搞定,基本上服务器这块应该是难不倒了。

下面说说我应该怎么做:

首先是建立前后端的通信协议:

request:

username/password, 约定username与password  各占32个字节(联同末位0)

response:

time_t 格式


由于通信内容简单,选择二进制传输,而不选择http,当然如果要考考 http 协议的了解,那就另当别论了。

请回头对题目认真看看,或者自己也可以写写,这里没有放代码,是因为我打算连载,请关注啦。

下篇我给大家写客户端程序先。


作者:xiaofei_hah0000 发表于2013-3-31 11:42:55 原文链接
阅读:95 评论:0 查看评论

    
[2]搭建一个后台服务器--客户端
    来源: 互联网  发布时间: 2013-10-19

上篇规定的协议请求部分:

request:

username/password, 约定username与password  各占32个字节(联同末位0)


可以将客户端的逻辑设计成:

1.将username,password  封装进buffer

2.连接服务端

3.发送buffer

4.接收二进制的系统当前时间 

5.显示时间 


代码如下:

服务端地址设置部分:

 addr_server.sin_family = AF_INET;
 addr_server.sin_port = htons( port );
 addr_server.sin_addr.s_addr = inet_addr( ip );

创建连接:

sock_client = socket( AF_INET, SOCK_STREAM, 0 );

连接服务端代码:

flag = connect( sock_client, ( struct sockaddr* ) &addr_server, sizeof( addr_server ) );

设置buffer填充username/password代码:

sprintf(buffer, "%s", "username");
sprintf(buffer + 32, "%s", "password" );

buffer[31]=buffer[63] = 0;

接着是发送:

flag = send( sock_client, buffer, 64, 0 );
if( flag == 64 )
{   
      printf( "send ok\n"); 
}

接收部分代码:

 flag = recv( sock_client, buffer, 64, 0 );
 if( flag != sizeof( time_t ) )
 {
        printf( "recv does not follow protocal\n");
        close( sock_client );
        continue;
 }


将接收到的二进制数据转成时间

memcpy( curtime, buffer, sizeof( time_t ) );
struct tm *ptm = localtime( curtime );


显示时间:

printf( "system time:%04d-%02d-%02d-%02d:%02d:%02d\n", 
	ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
	ptm->tm_hour, ptm->tm_min, ptm->tm_sec );



关闭连接:

 printf( "ok,now we close connection\n" );
 close( sock_client );



实际开发中,为了追求并发效率和提升搞压效果,客户端需要有一个循环,另外可以多进程同时操作。

实际测试中,我发现客户端的单进程并发量大概在1万左右,因此多开几个程序,已经可以满足需求了。


详细代码下载地址,因为要扣1分,非需要请勿下载:

下载地址


作者:xiaofei_hah0000 发表于2013-3-31 14:08:51 原文链接
阅读:84 评论:0 查看评论

    
[3]搭建一个后台服务器--服务端(异步,大并发)
    来源: 互联网  发布时间: 2013-10-19

上篇的阻塞模式下服务器的并发只有几K,而真正的server 像nginx, apache, yumeiz 轻轻松松处理几万个并发完全不在话下,因此大并发的场合下是不能用阻塞的。

1W的并发是一个分隔点,如果单进程模型下能达到 的话,说明至少在服务器这块你已经很厉害了。

服务器开发就像一门气功,能不能搞出大并发,容错性处理得怎么样,就是你有没有内功,内功有多深。


异步模式是专门为大并发而生,linux下一般用 epoll 来管理事件,下面就开始我们的异步大并发服务器实战吧。

跟阻塞开发一样,先来看看设计过程:

1.创建事件模型。

2.创建监听连接并监听。

3.将监听连接加入事件模型。

4.当有事件时,判断事件类型。

5.若事件为监听连接,则产生客户连接同时加入事件模型,对客户连接接收发送。

6.若事件为客户连接,处理相应IO请求。


为了让大家一概全貌,我用一个函数实现的( 一个函数写一个2W并发的服务器,你试过么),可读性可能会差点,但是对付这道面试题是绰绰有余了。

实际开发过程如下:

先定义一个事件结构,用于对客户连接进行缓存

struct my_event_s
{
	int fd;
	char recv[64];
	char send[64];

	int rc_pos;
	int sd_pos;
};

建立缓存对象:

struct epoll_event wait_events[ EPOLL_MAX ]; //事件模型的缓存
struct my_event_s my_event[ EPOLL_MAX ];     //连接对象的缓存
(未完,先休息会)


作者:xiaofei_hah0000 发表于2013-3-31 18:31:42 原文链接
阅读:0 评论:0 查看评论

    
最新技术文章:
▪用户及权限基础 2---- Linux权限    ▪用户及权限基础 3---- Linux扩展权限    ▪git 简明教程(1) --创建及提交
▪背包 代码    ▪json对象的封装与解析    ▪01背包,完全背包,多重背包 ,模板代码
▪apache安装详解    ▪HDU 4668 Finding string (解析字符串 + KMP)    ▪《TCP-IP详解 卷1:协议》学习笔记(二)
▪《TCP-IP详解 卷1:协议》学习笔记(持续更新...    ▪windows下使用swig    ▪gensim试用
▪Linux Shell脚本编程--nc命令使用详解    ▪solr对跨服务器表联合查询的配置    ▪递归和非递归实现链表反转
▪Linux磁盘及文件系统管理 1---- 磁盘基本概念    ▪Cholesky Decomposition    ▪HTTP协议学习
▪用C语言写CGI入门教程    ▪用hdfs存储海量的视频数据的设计思路    ▪java多线程下载的实现示例
▪【原创】eAccelerator 一个锁bug问题跟踪    ▪hadoop学习之ZooKeeper    ▪使用cuzysdk web API 实现购物导航类网站
▪二维数组中的最长递减子序列    ▪内嵌W5100的网络模块WIZ812MJ--数据手册    ▪xss 跨站脚本攻击
▪RobotFramework+Selenium2环境搭建与入门实例    ▪什么是API    ▪用PersonalRank实现基于图的推荐算法
▪Logtype    ▪关于端口号你知道多少!    ▪Linux基本操作 1-----命令行BASH的基本操作
▪CI8.7--硬币组合问题    ▪Ruby on Rails 学习(五)    ▪如何使用W5300实现ADSL连接(二)
▪不允许启动新事务,因为有其他线程正在该会...    ▪getting start with storm 翻译 第六章 part-3    ▪递归求排列和组合(无重复和有重复)
▪工具类之二:RegexpUtils    ▪Coding Interview 8.2    ▪Coding Interview 8.5
▪素因子分解 Prime factorization    ▪C# DllImport的用法    ▪图的相关算法
▪Softmax算法:逻辑回归的扩展    ▪最小生成树---Kruskal算法---挑战程序设计竞赛...    ▪J2EE struts2 登录验证
▪任意两点间的最短路径---floyd_warshall算法    ▪Sqoop实现关系型数据库到hive的数据传输    ▪FFMPEG采集摄像头数据并切片为iPhone的HTTP Stream...
▪Ubuntu 13.04 – Install Jetty 9    ▪TCP/IP笔记之多播与广播    ▪keytool+tomcat配置HTTPS双向证书认证
▪安装phantomjs    ▪Page Redirect Speed Test    ▪windows media player 中播放pls的方法
▪sre_constants.error: unbalanced parenthesis    ▪http headers    ▪Google MapReduce中文版
▪The TCP three-way handshake (connect)/four wave (closed)    ▪网站反爬虫    ▪Log4j实现对Java日志的配置全攻略
▪Bit Map解析    ▪Notepad 快捷键 大全    ▪Eclipse 快捷键技巧 + 重构
▪win7 打开防火墙端口    ▪Linux Shell脚本入门--awk命令详解    ▪Linux Shell脚本入门--Uniq命令
▪Linux(Android NDK)如何避免僵死进程    ▪http Content-Type一览表    ▪Redis实战之征服 Redis + Jedis + Spring (二)
▪Tomcat7.0.40 基于DataSourceRealm的和JDBCRealm的资源...    ▪利用SQOOP将ORACLE到HDFS    ▪django输出 hello world
▪python re    ▪unity3D与网页的交互    ▪内存共享基本演示
▪python join    ▪不再为无限级树结构烦恼,且看此篇    ▪python实现变参
▪打开文件数限制功能不断地制造问题    ▪Arduino Due, Maple and Teensy3.0 的 W5200性能测试    ▪Selenium实例----12306网站测试
▪基于协同过滤的推荐引擎    ▪C4.5决策树    ▪C#HTTP代理的实现之注册表实现
▪nosql和关系型数据库比较?    ▪如何快速比较这两个字符串是否相等?    ▪hdoj 1863 畅通工程 最小生成树---prime算法
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3