网络编程——客户/服务器程序设计范式

网络编程
  • 我们在需要开发一个服务器程序时,有较多的的程序设计范式可供选择,不同范式有其自身的特点和实用范围,明了不同范式的特性有助于我们服务器程序的开发。
  • 客户端程序通常比服务器容易些,当然客户端程序也可以使用这些程序设计范式,因为它们蕴含的道理都是想通的。
  • 本文所设计的服务器主要是指基于TCP的服务器

迭代服务器

迭代TCP服务器 总是在完全处理某个客户的请求之后才开始下一个客户的请求处理
这样的服务器实际中比较少见。
基于UDP的大多服务器却是这样实现

并发服务器,每个客户请求fork一个子进程

传统并发服务器 调用fork派生一个子进程来处理每个客户,这使得服务器能够同时为多个客户服务,每个进程一个客户
客户数目的唯一限制是操作系统对其能够同时拥有多少子进程的限制。
绝大多数TCP服务器程序都是按这个范式编写。
并发服务器的问题在于为每个客户现场fork一个子进程比较耗费CPU时间。

预先派生子进程,每个子进程无保护地调用accept

不同于传统意义的并发服务器那样为每个客户现场派生一个子进程,而是 在启动阶段预先派生一定数量的子进程,当有客户连接到达时,这些子进程就能立即为它提供服务
这种技术的有点在于无需引入父进程执行fork的开销就能处理新到来的客户。缺点是父进程必须在服务启动阶段猜测需要预先派生多少子进程。如果某个时刻客户数恰好等于子进程总数,那么新到的客户将被忽略,直到至少有一个子进程完成处理重新可用。

预先派生子进程,使用文件上锁保护accept

在多个进程中引用同一个监听套接字的描述符上调用accept的做法在某些系统实现是不被支持的,那么解决办法是让应用进程在调用accept前后安装某种形式的锁(lock),这样任意时刻只有一个子进程阻塞在accept调用中,其他子进程则阻塞在获取保护accept的锁上。
这里使用文件锁来保护,文件锁涉及到文件系统的操作,可能比较耗时。

预先派生子进程,使用线程互斥锁上锁保护accept

相比于 预先派生子进程,使用文件上锁保护accept,使用线程锁保护accept,这种方法 不仅适用于同一进程内各个线程间的锁保护,而且能够用于不同进程之间的锁保护
在不同进程间的锁保护需要注意的是

  • 互斥锁变量必须存放在由所有进程共享的内存区中
  • 必须告知线程函数库这个锁是用于不同进程间共享的互斥锁

预先派生子进程,父进程向子进程传递套接字描述符

只让父进程嗲用accept,然后把所接受的已经连接的套接字 传递 给某个子进程。
这样绕过了为所有子进程的accept调用提供上锁保护的需求,但是需要从父进程到子进程进行某种形式的描述符传递。
这种技术会上代码比较复杂,父进程必须跟踪子进程的闲忙状态,以便于给空闲的子进程传递新的套接字。

并发服务器,每个客户端请求创建一个线程

相比于多进程模型,如果服务器主机提供支持线程,我们可以改用线程以取代进程。线程相比于进程的优势这里不再累述。

预先创建线程服务器,使用互斥锁上锁保护accept

相比预先派生一个子进程池快于为每个客户线程fork一个子进程池类似的道理,在有线程支持的系统上,预先创建的线程池取代为每个客户现场创建一个线程的做法有类似的性能提升。
这种模式的基本设计是预先创建一个线程,并让每个线程各自调用accept,取代让每个线程都阻塞在accept调用中的做法,使用互斥锁保证任何时刻只有一个线程在调用accept。

预先创建线程服务器,由主线程调用accept

程序启动阶段创建一个线程池后让主线程调用accept;
主线程把每个客户连接传递给池中某个可用的线程,类似于进程版本的做法。
这样的设计问题在于主线程如何将一个已连接套接字传递给线程池中某个可用线程

我们有很多实现手段,本可用如前面一样使用描述符传递,但是既然所有线程和所有描述符都在同一个进程中,那么也就没有必要把一个描述符从一个线程传递到另一个线程。接收线程只需要知道这个已连接套接字描述符的值(传递描述符可不只是传递这个值,事实上是需要传递这个套接字的引用,因此也将返回一个不同于原值的描述符,该套接字的引用计数也会增加

总结

  • 系统负载较轻时,每来一个客户请求现场派生一个子进程为之服务的传统并发服务器程序模型就足够了
  • 相比传统的每个客户fork一次设计范式,预先创建一个子进程池或一个线程池的范式能够把进程控制CPU时间降低10倍或以上。编写这些范式的程序并不会复杂,不过会有额外的工作,比如监视现在子进程数,随着所服务客户数的动态变化而增加或减少这个数目
  • 某些实现允许多个子进程或线程阻塞在同一个accept调用中,另外的实现却要求对accept调用需要某种类型的锁加以保(文件锁或者互斥锁等)
  • 让所有子进程或线程自行调用accept通常比让父进程或主线程独自调用accept并把描述符传递个子进程或线程来的简单和快捷
  • 由于潜在select冲突的原因,让所有子进程或线程阻塞在同一accept调用中比让他们阻塞在同一个select调用中更可取。
  • 使用 线程通常远快于使用进程,不过选择每个客户一个子进程还是每个客户一个线程取决于操作系统提供什么支持(某些系统不提供线程支持),还可能取决于为服务每个客户需要激活其他什么程序。例如,如果accept客户连接的服务器调用fork和exec,那么fork一个单线程的进程可能快于fork一个多线程的进程,另外还有资源等方面的综合考虑。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • 《UNIX 网络编程卷一:套接字联网API》笔记 套接字 套接字编程接口,是在 TCP/IP 协议族中,应用层进入...
    超net阅读 5,777评论 2 13
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • 芒格:只投简单能懂的股 价值投资理念的基石模型: 1.安全边际模型 2.护城河模型 3.非连续性模型 4.能力圈模...
    曹翊丹阅读 228评论 0 0
  • 我好像看到了希望,看到了美好的童话般的未来,但可惜这只是希望而已,现实总会不经意地撕开伪装,给你当头一棒。读完《传...
    Aeimqzxvt阅读 1,307评论 0 2
  • 忐忑给你 心跳给你 彻夜长谈的星光给你 手给你 怀抱给你 跋涉给你 无人的夜晚的等待给你 一腔孤勇和一湾宁静 全都...
    流年已尽阅读 325评论 0 0