导图社区 网络程序设计
根据网络程序设计课程所学,简略画的思维导图,可能有疏漏
编辑于2020-06-03 17:15:08网络程序设计
课程背景
掌握Linux下C/C++编程
熟悉TCP/IP协议基本原理
熟练掌握socket编程
掌握提高网络编程效率的手段
掌握网络软件模型及设计
客户服务模型基础
动机-解决汇聚点问题
同一时刻双方互发消息概率很低
通信的一方启动执行后一直等待对方的联系更加可靠
当有一方一直运行时,不必再增加TCP/IP复杂性,有效减轻了下层协议软件复杂性
概念
通信发起方向来区分
客户端:发起对等通信的应用程序
每次执行都与服务器练习
容易构建,往往不需要系统特权
属于常规的网络应用程序
服务器:等待接收客户通信请求的程序
接收客户通信请求
执行必要的操作
返回结构给客户
体系结构
服务器
总是打开的主机
具有固定的、众所周知的公网IP地址
主机群集常被用于创建强大的虚拟服务器
客户机
同服务器端通信
可以间断的同服务器连接
可以用于动态IP地址
客户机相互之间不直接通信
服务器特权和复杂性
服务器经常需要访问受操作系统保护的资源:需要系统特权
服务器不能把特权传递给使用服务的用户
服务器需要处理安全问题
鉴别
授权
数据安全
保密
保护
特权和并发导致了服务器软件的复杂性
socket编程基础
socket
IPv4套接口地址结构
通用地址结构
网络字节序
字节序
大端字节序
小端字节序
网络字节序
主机字节序
字节序转换函数
地址转换函数
套接字类型
TCP客户/服务器模型
回射客户/服务器
socket
bind
listen
accept
服务器软件设计的算法和问题
简单算法
创建套接字
绑定到一个熟知端口
期望在这个端口上接收请求
进入循环,接收客户请求并应答
并发服务器和循环服务器
循环服务器:一个时刻只处理一个请求
并发服务器:一个时刻表面看起来可以处理多请求
无连接和面向连接的服务器访问
选择面向连接或者无连接的服务,依赖于应用程序的需求
面向连接
TCP是面向连接的
点到点通信
建立可靠连接
可靠交付
具有流控的传输
双工传输
流模式
优点
易于编程
自动处理分组丢失,分组失序
自动验证数据差错,处理连接状态
缺点
对每个连接都有一个单独的套接字,耗费更多资源
在空闲的连接上不发送任何分组
始终运行的服务器会因为客户的崩溃,导致无用套接字的过多而耗尽资源,终止运行
无连接的
UDP是无连接的
多对多通信
不可靠服务
缺乏流控制
报文模式
优点:没有资源耗尽问题
缺点
需要自己完成可靠通信问题
支持组播和广播的服务器必须是无连接的
无状态和有状态的服务器应用
概念
状态信息:服务器维护的,关于它和客户正进行的交互状态信息
无状态服务器:没有保留任何状态信息
状态服务器:维护状态信息的服务器
状态问题源于确保可靠性的要求(特别对无连接)
传输协议不能保证可靠,应用协的设计必须保证可靠
优化无状态服务器
在服务器加入大的文件缓存和上述的信息表格
需要小心:检查文件名、文件偏移等,重复、失序问题
如果客户出了故障重新启动,将会重新获得一个不同的端口号,先前的表项会失去作用,最终会耗尽服务器资源
服务器可以选择删除LRU
四种基本类型的服务器
通过TCP的面向连接的循环服务器
创建套接字并绑定到它所提供服务的熟知端口上(socket、bind)
将该端口设置为被动模式,使其准备为服务器所用(listen)
从该套接字上接收下一个连接请求,获得该连接的新的套接字(accept)
在新套接字上重复读取来自客户的数据,构造响应,按照应用协议向客户发回响应
当某个特定客户完成交互时,关闭连接,返回步骤三接收新的连接
无连接循环服务器的算法
创建套接字并将其绑定到所提供的服务的熟知端口上
重复读取来自客户的请求,构造响应,按照应用协议向客户发回响应
并发的无连接的服务器算法
主1、创建套接字并将其绑定到所提供服务的熟知地址上。让该套接字保持为未连接的
主2、反复调用recvfrom接收来自客户的下一个请求,创建一个新的从线程来处理响应
从1、从来自主线程的特定请求以及到该套接字的访问开始
从2、根据应用协议构造应答,并用sendto将该应答发回给客户
从3、退出(即:从线程处理完一个请求后就终止)
并发的面向连接服务器算法
主1、创建套接字并将其绑定到所提供服务的熟知地址上。让该套接字保持为无连接的
主2、将该端口设置为被动模式
主3、反复调用accept以便接收来自客户的下一个连接请求,并创建新的从线程或者进程来处理响应
从1、由主线程传递来的连接请求开始
从2、用该连接与客户进行交互;读取请求并发回响应
从3、关闭连接并退出
单线程实现并发、面向连接的服务器算法
创建套接字并将其绑定到这个服务的熟知端口上,将该套接字加到一个表中,该表中的项是可以进行I/O的描述符
使用select在已经有的套接字上等待I/O主题
如果最初的套接字准备就绪,使用accept获得下一个连接,并将这个新的套接字加入到表中,该表中的项是可以进行I/O的描述符
如果最初的套接字以外的套接字就绪,就使用recv或read获得下一个请求,构造响应,用send或者write将响应发回给客户
继续按照以上的步骤2进行处理
小结
循环无连接服务器
对每个请求的处理少,通常为无状态的
循环的面向连接服务器
要求可靠传输的,对每个请求处理少的服务
并发的,无连接的服务器
不常见,为每个请求创建一个新线程或进程
并发的面向连接的服务器
最一般的。可靠传输,并发处理多个请求
多进程可以是多个独立的程序
多线程(进程)或者单线程方式
服务器
使用场合
循环的和并发的
如果循环方案产生的响应时间对应用来说足够,就可以使用循环;否则需要并发
真正的和表面上的并发性
创建线程或切换环境的开销大,服务器需要在多个连接之间共享或者交换数据,用单线程
使用线程开销不大,服务器需要在多个连接之间共享或者交换数据,用多线程;
每个进程可以孤立运行或者要得到最大并发性,使用多进程
面向连接的和无连接的
当应用协议处理了可靠性问题,或者应用在局域网环境内时,使用无连接的传输。否则使用有连接传输
死锁(服务器不能回答请求)
循环的面向连接的服务器
某个客户和服务器建立一个连接,客户不再发送请求,服务器无法使用recv得到请求,服务器将在这里阻塞
客户不能正常工作,不处理服务器的响应
客户接收窗口填满
而服务器的外发存储数据区填满阻塞
可能阻塞的系统调用会产生死锁
如没有本地缓存时(发方存放已发数据),发送方send或者write会阻塞;进而导致接收方recv或者read调用也将阻塞。
单线程的服务器会被阻塞死锁
主题
服务器的并发性的统一,高效管理
并发等级
定义:在某个给定的时刻一个服务器正在运行着的执行线程/进程总数
服务器整个生命周期中,同时并发的最大线程数
某种意义上代表了服务器最大资源开销
需求驱动并发
为增加灵活性,当收到远程连接请求时触发线程/进程创建
服务器的并发等级依赖于客户的需求
代价:线程或进程创建都要消耗资源
额外开销和时延
为每个请求创建一个新进程/线程,开销昂贵
带来处理的时延:创建进程/线程需要较长的时间
消耗系统资源
从线程/进程预分配
概述
预分配线程/进程,当创建进程/线程时间较长的时候,也能维持高吞吐量
主服务器在开始执行时就创建N个从进程/线程
将所接受的新的请求分配给这N个从进程/线程中的一个处理
进程/线程并不退出
优点:操作系统的额外开销低,降低了服务器时延
面向连接服务器中的预分配
互斥、文件锁定和accept并发调用
无连接服务器中的预分配
算法:多个从线程同时绑定在一个socket上调用recvfrom获得发送方的地址和其发送的数据报,并调用sendto应答。一个数据报到达的时候系统只唤醒一个从进程
延迟的从线程/进程预分配
复杂服务器
多协议服务器
循环多协议服务器
单进程并发多协议服务器
DAYTIME例子
共享代码
多服务服务器
循环无连接、多服务服务器
循环面向连接的、多服务服务器
并发、面向连接、多服务服务器
单进程、表面并发面向连接多服务器
从多服务服务器调用单独的程序
解决:缺乏灵活性,改变任何一个服务的代码都需要编译整个服务器
多协议多服务服务器
并发服务器
类型
并发的面向连接的服务器
并发无连接服务器
适用场景
循环服务器
使用并发服务器
避免了长时间的延迟,不允许单个客户占用所有的资源,使服务器与许多客户同时进行通信
客户感觉服务器提供了较短的响应时间
功能
多个客户打开到某个服务器的连接,然后在该连接上重复发送数据,并读取从服务器返回的回显
服务器响应每个客户,接收连接,读取来自该客户的数据,并原样返回给数据
两种形式
创建多个进程,每个进程都有一个执行线程
在一个进程中创建多个执行线程
并发面向连接单进程
线程
linux线程特点
动态创建
并发执行
抢先
私有局部变量
共享全局变量
共享文件描述符
协调和同步函数
线程优点
更高效:上下文切换的额外开销减少
上下文切换:线程切换需要执行的命令
同一进程中两个线程比不同进程中两个线程切换要快
进程内的线程切换不用改变虚拟存储器的映射
共享存储
并发服务器中的多个副本需要相互通信或访问共享的数据
利用线程容易构造监控系统
线程缺点
由于线程间共享存储和进程状态,一个线程动作可能对同一个进程内的其他线程产生影响
两个线程如果同一时间访问同一个变量,会产生相互干扰
调用一个静态的数据项的库函数不是线程安全的,覆盖会导致错误
缺乏健壮性,一个线程出错,服务器将会终止整个进程
循环服务器
概述
类型
循环无连接服务器
循环面向连接的服务器
特点
每次处理时间都很短
服务器实现简单
无连接的——Time服务器实例
面向连接的——Daytime服务器实例