网络应用
- 网络应用体系结构
- 客户机/服务器
- P2P
- 混合结构
- 网络应用的服务需求
- 可靠性
- 带宽
- 时延
- Internet传输层服务模型
- TCP
- UDP
- 特定网络应用及协议
- HTTP
- SMTP, POP, IMAP
- DNS
- P2P应用
- Socket编程
- TCP
- UDP
网络应用的体系结构
- 客户机/服务器结构(Client-Server, C/S)
- 点对点结构(Peer-to-peer, P2P)
- 混合结构(Hybrid)
客户机/服务器结构(Client-Server, C/S)(如:Web应用)
- 服务器
- 7*24小时提供服务
- 永久性访问地址/域名
- 利用大量服务器实现可扩展性
- 客户机
- 与服务器通信,使用服务器提供的服务间歇性接入网络
- 可能使用动态IP地址
- 不会与其他客户机直接通信
纯P2P结构(如:文件下载BT,BitTorrent)
- 没有永远在线的服务器
- 任意端系统/节点之间可以直接通讯
- 节点间歇性接入网络
- 节点可能改变IP地址
优点: 高度可伸缩
缺点: 难于管理
混合结构
- Napster
网络应用的基础: 进程间通信
- 进程
- 主机上运行的程序
- 同一主机上运行的进程之间如何通信?
- 进程间通信机制
- 操作系统提供
- 不同主机上运行的进程间如何通信?
- 消息交换
客户机进程: 发起通信的进程
服务器进程: 等待通信请求的进程
套接字: Socket
- 进程间通信利用socket发送/接收消息实现
- 类似于寄信
- 发送方将消息送到门外邮箱
- 发送方依赖(门外的)传输基础设施将消息传到接收方所在主机,并送到接收方的门外
- 接收方从门外获取消息
- 传输基础设施向进程提供API
- 传输协议的选择
- 参数的设置
如何寻址进程?
Q: 不同主机上的进程间通信,那么每个进程必须拥有 标识符
如何寻址主机? —— IP地址
Q:主机有了IP地址后,是否足以定位进程?
A:否。同一主机上可能同时有多个进程需要通信。
- 端口号/Port number
- 为主机上每个需要通信的进程分配一个 端口号
- HTTPserver: 80
- Mail Server : 25
- 进程的标识符
- IP地址+端口号
应用层协议
- 网络应用需遵循应用层协议
- 公开协议
- 由RFC(Request For Comments)定义
- 允许互操作
- HTTP,SMTP,……
- 私有协议
- 多数P2P文件共享应用
应用层协议的内容
- 消息的类型(type)
- 请求消息
- 响应消息
- 消息的语法(syntax)/格式
- 消息中有哪些字段(field) ?
- 每个字段如何描述
- 字段的语义(semantics)
- 字段中信息的含义
- 规则(rules)
- 进程何时发送/响应消息
网络应用对传输服务的需求
- 数据丢失(data loss)/可靠性(reliability)
- 某些网络应用能够容忍一定的数据丢失:网络电话
- 某些网络应用要求100%可靠的数据传输:文件传输,telnet
- 时间(timing)/延迟(delay)
- 有些应用只有在延迟足够低时才“有效”
- 网络电话/网络游戏
- 带宽(bandwidth)
- 某些应用只有在带宽达到最低要求时才“有效”:网络视频
- 某些应用能够适应任何带宽——弹性应用: email
Internet提供的传输服务
- TCP服务
- 面向连接:客户机/服务器进程间需要建立连接
- 可靠的传输
- 流量控制:发送方不会发送速度过快,超过接收方的处理能力
- 拥塞控制:当网络负载过重时能够限制发送方的发送速度
- 不提供时间/延迟保障
- 不提供最小带宽保障
- UDP服务
- 无连接
- 不可靠的数据传输
- 不提供:
- 可靠性保障
- 流量控制
- 拥塞控制
- 延迟保障
- 带宽保障
Web与HTTP
Web
- World Wide Web:
- Tim Berners-Lee
- 网页
- 网页互相链接
- 网页(Web Page)包含多个对象(objects)
- 对象:HTML文件、JPEG图片、视频文件、动态脚本等
- 基本HTML文件:包含对其他对象引用的链接
- 对象的寻址(addressing)
URL(Uniform Resource Locator): 统一资源定位器 RFC 1738
Scheme : //host:port/path
HTTP
万维网应用遵循什么协议?
- 超文本传输协议 HTTP
- HyperText Transfer Protocol
- C/S 结构
- 客户—Browser:请求、接收、展示Web对象
- 服务器Web Server:响应客户的请求,发送对象
- HTTP版本:
- 1.0: RFC 1945
- 1.1: RFC 2068
- 使用TCP传输服务
- 服务器在80端口等待客户的请求
- 浏览器发起到服务器的TCP连接(创建套接字Socket)
- 服务器接受来自浏览器的TCP连接
- 浏览器(HTTP客户端)与Web服务器(HTTP服务器)交换HTTP消息
- 关闭TCP连接
- 无状态(stateless)
- 服务器不维护任何有关客户端过去所发请求的信息
HTTP连接的两种类型
- 非持久性连接(Nonpersistent HTTP)
- 每个TCP连接最多允许传输 一个 对象
- HTTP 1.0版本使用非持久性连接
- 持久性连接(Persistent HTTP)
- 每个TCP连接允许传输 多个 对象
- HTTP 1.1版本默认使用持久性连接
非持久性连接
响应时间分析与建模
- RTT(Round Trip Time)
- 从客户端发送一个很小的数据包到服务器并返回所经历的时间
- 响应时间(Response time)
- 发起、建立TCP连接: 1个RTT
- 发送HTTP请求消息到HTTP响应消息的前几个字节到达: 1个RTT
- 响应消息中所含的文件/对象传输时间
- Total=2RTT+文件发送时间
非持久性连接的问题
- 每个对象需要2个RTT
- 操作系统需要为每个TCP连接开销资源(overhead)
- 浏览器会怎么做?
- 打开多个并行的TCP连接以获取网页所需对象
- 给服务器端造成什么影响?
持久性连接
- 发送响应后,服务器保持TCP连接的打开
- 后续的HTTP消息可以通过这个连接发送
- 无流水(pipelining)的持久性连接
- 客户端只有收到前一个响应后才发送新的请求
- 每个被引用的对象耗时1个RTT
- 带有流水机制的持久性连接.
- HTTP1.1的默认选项
- 客户端只要遇到一个引用对象就尽快发出请求
- 理想情况下,收到所有的引用对象只需耗时约1个RTT
HTTP请求消息
- HTTP协议有两类消息
- 请求消息(request)
- 响应消息(response)
- 请求消息
- ASCII: 人直接可读
HTTP请求消息的通用格式
上传输入的方法
- POST方法
- 网页经常需要填写表格(form)
- 在请求消息的消息体(entity body)中上传客户端的输入
- URL方法
- 使用GET方法
- 输入信息通过 request 行的 URL 字段上传
HTTP方法
HTTP/1.0
- GET
- POST
- HEAD
- 请Server不要将所请求的对象放入响应消息中
HTTP/1.1
- GET, POST, HEAD
- PUT
- 将消息体中的文件上传到URL字段所指定的路径
- DELETE
- 删除URL字段所指定的文件
HTTP响应状态代码
- 响应消息的第一行
- 示例
- 200 OK
- 301 Moved Permanently
- 400 Bad Request
- 404 Not Found
- 505 HTTP Version Not Supported
Cookie技术
Cookie技术:某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。
- RFC6265
Cookie的组件
- HTTP响应消息的cookie头部行。
- HTTP请求消息的cookie头部行。
- 保存在客户端主机上的cookie文件,由浏览器管理.
- Web服务器端的后台数据库
Cookie的原理
Cookie的作用
Cookie能够用于:
- 身份认证
- 购物车推荐
- Web e-mail
缺点: 隐私问题
Web缓存/代理服务器技术
- 功能
- 在不访问服务器的前提下满足客户端的HTTP请求。
- 为什么要发明这种技术?
- 缩短客户请求的响应时间
- 减少机构/组织的流量
- 在大范围内(Internet)实现有效的内容分发
- Web缓存/代理服务器
- 用户设定浏览器通过缓存进行Web访问
- 浏览器向缓存/代理服务器发送所有的HTTP请求
- 如果所请求对象在缓存中,缓存返回对象。
- 否则,缓存服务器向原始服务器发送HTTP请求,获取对象,然后返回给客户端并保存该对象
- 缓存既充当客户端,也充当服务器
- 一般由ISP(Internet服务提供商)架设
Q:如何保证缓存的内容是最新的?
A:条件性GET方法
目标:
- 如果缓存有最新的版本,则不需要发送请求对象
缓存:
- 在HTTP请求消息中声明所持有版本的日期
- if-modified-since:
服务器:
- 如果缓存的版本是最新的,则响应消息中不包含对象
- HTTP/1.0 304 Not Modified
Email应用的构成(1)
- Email应用的构成组件
- 邮件客户端(user agent)
- 邮件服务器
- SMTP协议(Simple Mail Transfer Protocol)
邮件客户端
- 读、写Email消息
- 与服务器交互,收、发Email消息
- Outlook, Foxmail, Thunderbird
- Web客户端
邮件服务器(Mail Server)
- 邮箱:存储发给该用户的Email
- 消息队列(message queue):存储等待发送的Email
SMTP协议
- 邮件服务器之间传递消息所使用的协议
- 客户端:发送消息的服务器
- 服务器:接收消息的服务器
SMTP协议: RFC 2821
- 使用TCP进行email消息的可靠传输
- 端口25
- 传输过程的三个阶段
- 握手
- 消息的传输
- 关闭
- 命令/响应交互模式
- 命令(command): ASCII文本
- 响应(response): 状态代码和语句
- Email消息只能包含7位ASCII码
- 使用持久性连接
- 要求消息必须由7位ASCII码构成
- SMTP服务器利用CRLF.CRLF确定消息的结束。
SMTP 与 HTTP 协议对比:
- HTTP: 拉式(pull)
- SMTP: 推式(push)
- 都使用命令/响应交互模式
- 命令和状态代码都是 ASCll 码
- HTTP: 每个对象封装在独立的响应消息中
- SMTP: 多个对象在由多个部分构成的消息中发送
Email消息格式
- SMTP: email消息的传输/交换协议
- RFC822:文本消息格式标准
- 头部行(header)
- To
- from ,与SMTP命令不同
- Subject
- 头部行(header)
- 消息体(body)
- 消息本身
- 只能是ASCII字符
- Email消息格式:多媒体扩展
- MIME:多媒体邮件扩展 RFC 2045, 2056
- 通过在邮件头部增加额外的行以声明 MIME 的内容类型
邮件访问协议
邮件访问协议: 从服务器获取邮件
- POP: Post Office Protocol [RFC 1939]
- 认证/授权(客户端<→服务器)和下载
- IMAP: Internet Mail Access Protocol[RFC 1730]
- 更多功能
- 更加复杂
- 能够操纵服务器上存储的消息
- HTTP: 163,QQ Mail等。
POP协议(无状态)
- 认证过程
- 客户端命合
- User: 声明用户名.
- Pass:声明密码
- 服务器响应
- +OK
- 一ERR
- 客户端命合
- 事务阶段
- List:列出消息数量
- Retr :用编号获取消息
- Dele:删除消息
- Quit
“下载并删除”模式
- 用户如果换了客户端软件,无法重读该邮件
“下载并保持”模式:
- 不同客户端都可以保留消息的拷贝
POP3是无状态的
IMAP协议(有状态)
- 所有消息统一保存在一个地方:服务器
- 允许用户利用文件夹组织消息
- IlMAP支持跨会话(Session)的用户状态:
- 文件夹的名字
- 文件夹与消息ID之间的映射等
DNS: Domain Name System
DNS 使用 UDP 传输协议
- Internet上主机/路由器的识别问题
- IP地址
- 域名: www.hit.edu.cn
- 问题:域名和IP地址之间如何映射?
- 域名解析系统DNS
- 多层命名服务器构成的分布式数据库
- 应用层协议:完成名字的解析
- Internet核心功能,用应用层协议实现。
- 网络边界复杂
DNS提供的服务
- 域名向IP地址的翻译
- 主机别名
- 邮件服务器别名
- 负载均衡:Web服务器
问题:为什么不使用集中式的DNS?
- 单点失败问题
- 流量问题
- 距离问题
- 维护性问题
DNS是分布式且不可伸缩的!
DNS根域名服务器
- 本地域名解析服务器无法解析域名时,访问根域名服务器
- 根域名服务器
- 如果不知道映射,访问权威域名服务器获得映射
- 向本地域名服务器返回映射
TLD和权威域名解析服务器
- 顶级域名服务器(TLD, top-level domain): 负责com, org, net, edu等顶级域名和国家顶级域名,例如 cn, uk, fr 等
- Network Solutions 维护 com 顶级域名服务器
- Educause 维护 edu 顶级域名服务器
- 权威(Authoritative)域名服务器: 组织的域名解析服务器,提供组织内部服务器的解析服务
- 组织负责维护
- 服务提供商负责维护
本地域名解析服务器
- 不严格属于层级体系
- 每个ISP有一个本地域名服务器
- 默认域名解析服务器
- 当主机进行DNS查询时,查询被发送到本地域名服务器
- 作为代理(proxy),将查询转发给(层级式)域名解析服务器系统
查询方式
- 迭代查询
- 递归查询
DNS记录缓存和更新
只要域名解析服务器获得域名—IP映射,即缓存这一映射
- 一段时间过后,缓存条目失效(删除)
- 本地域名服务器一般会缓存顶级域名服务器的映射,因此根域名服务器不经常被访问
DNS记录
- 资源记录(RR, resourcerecords)
- RRformat:(name,value,type, ttl)
- Type=A
- Name:主机域名
- Value: IP地址
- Type=NS
- Name:域(edu.cn)
- Value:该域权威域名解析服务器的主机域名
- Type=CNAME
- Name:某一真实域名的别名
- www.ibm.com -servereast.backup2.ibm.com
- Value:真实域名
- Name:某一真实域名的别名
- Type=MX
- Value是与name相对应的邮件服务器
DNS协议与消息
- DNS协议:
- 查询(query)和回复(reply消息)
- 消息格式相同
- 消息头部
- identification: 16位查询编号,回复使用相同的编号
- flags
- 查询或回复
- 期望递归
- 递归可用
- 权威回答
P2P结构
P2P:搜索信息
P2P系统的索引:信息到节点位置(IP地址+端口号)的映射
- 文件共享(电驴)
- 利用索引动态跟踪节点所共享的文件的位置
- 节点需要告诉索引它拥有哪些文件
- 节点搜索索引,从而获知能够得到哪些文件
- 即时消息(QQ)
- 索引负责将用户名映射到位置
- 当用户开启IM应用时,需要通知索引它的位置
- 节点检索索引,确定用户的IP地址
索引类型:
- 集中式索引
- Napster 最早采用这种设计
集中式索引的问题:
内容和文件传输是分布式的, 但是内容定位是高度集中式的
- 单点失效问题
- 性能瓶颈
- 版权问题
洪泛式查询: Query flooding
完全分布式架构
Gnutella采用这种架构
每个节点对它共享的文件进行索引,且只对它共享的文件进行索引
覆盖网络(overlay network): Graph
- 节点X与Y之间如果有TCP连接,那么构成一个边
- 所有的活动节点和边构成覆盖网络
- 边:虚拟链路
- 节点一般邻居数少于10个
查询消息通过已有的TCP连接发送
节点转发查询消息
如果查询命中,则利用反向路径发回查询节点
- 层次式覆盖网络
- 介于集中式索引和洪泛查询之间的方法
- 每个节点或者是一个超级节点,或者被分配一个超级节点
- 节点和超级节点间维持TCP连接
- 某些超级节点对之间维持TCP连接
- 超级节点负责跟踪子节点的内容
应用编程接口API
应用编程接口API (Application Programming
Interface)
应用编程接口API: 就是应用进程的控制权和操作系统的控制权进行转换的一个系统调用接口.
几种典型的应用编程接口
- Berkeley UNIX操作系统定义了一种API,称为套接字接口(socket interface),简称套接字(socket) 。
- 微软公司在其操作系统中采用了套接字接口API,形成了一个稍有不同的API,并称之
为 Windows Socket Interface,WINSOCK - AT&T为其UNIX系统Ⅳ定义了一种API,简写
为 TLI (Transport Layer Interface)。
Socket API
- 最初设计
- 面向BSD UNIX-Berkley
- 面向TCP/IP协议栈接口
- 目前
- 事实上的工业标准
- 绝大多数操作系统都支持
- Internet网络应用最典型的API接口
- 通信模型
- 客户/服务器(C/S)
- 应用进程间通信的抽象机制
Q: 服务端有多个进程创建套接字时,客户端如何选择进程?
A:通过 IP地址+端口号
标识通信端点(对外):
- IP地址+端口号
操作系统/进程如何管理套接字(对内)?
- 套接字描述符( socket descriptor)
- 小整数
- 类似于文件的抽象
- 当应用进程创建套接字时,操作系统分配一个数据结构存储该套接字相关信息
- 返回套接字描述符
地址结构
已定义结构sockaddr_in
使用 TCP/IP 协议簇的网络应用程序声明端点地址变量时,使用结构sockaddr_in
Socket API 函数
- WSAStartup
int WSAStartup(WORD wVersionRequested, LPWSADATA IpWSAData);
使用 Socket 的应用程序在使用 Socket 之前必须首先调用WSAStartup
函数
两个参数:
- 第一个参数指明程序请求使用的WinSock版本,其中高位字节指明副版本、低位字节指明主版本.
- 十六进制整数,例如Ox102表示2.1版
- 第二个参数返回实际的WinSock的版本信息
- 指向
WSADATA
结构的指针
- 指向
- WSACleanup
int WSACleanup (void);
- 应用程序在完成对请求的Socket库的使用,最后要调用WSACleanup函数
- 解除与Socket库的绑定
- 释放Socket库所占用的系统资源
- socket
sd =socket(protofamily,type,proto);
- 创建套接字
- 操作系统返回套接字描述符( sd)
- 第一个参数(协议族): protofamily = PF_INET ( TCP/IP)
- 第二个参数(套接字类型):
- type = SOCK_STREAM, SOCK_DGRAM or SOCK_RAW ( TCP/IP)
- 第三个参数(协议号): 0 为默认
Socket面向TCP/IP的服务类型
- SOCK_STREAM
- SOCK_DGRAM
- SOCK_RAW
- TCP: 可靠、面向连接、字节流传输、点对点
- UDP: 不可靠、无连接、数据报传输
- Closesocket
int closesocket(SOCKET sd);
- 关闭一个描述符为sd的套接字
- 如果多个进程共享一个套接字,调用closesocket将套接字引用计数减1,减至0才关闭
- 一个进程中的多线程对一个套接字的使用无计数
- 如果进程中的一个线程调用
closesocket
将一个套接字关闭,该进程中的其他线程也将不能访问该套接字
- 如果进程中的一个线程调用
- 返回值:
- 0: 成功
- SOCKET_ERROR: 失败
- bind
int bind (sd ,localaddr ,addrlen) ;
- 绑定套接字的本地端点地址
- IP地址+端口号
- 参数:
- 套接字描述符(sd)
- 端点地址(localaddr)
- 结构sockaddr_in
- 客户程序一般不必调用 bind 函数
- 服务器端?
- 熟知端口号.
- IP地址? 地址通配符:
INADDR_ANY
- listen
int listen (sd ,queuesize) ;
- 置服务器端的流套接字处于监听状态
- 仅服务器端调用
- 仅用于面向连接的流套接字
- 设置连接请求队列大小( queuesize)
- 返回值:
- 0:成功
- SOCKET_ERROR:失败
- connect
connect (sd ,saddr , saddrlen) ;
- 客户程序调用connect函数来使客户套接字(sd)与特定计算机的特定端口( saddr)的套接字(服务)进行连接
- 仅用于客户端
- 可用于 TCP客户端 也可以用UDP客户端
- TCP客户端:建立TCP连接
- UDP客户端:指定服务器端点地址
- accept
newsock accept(sd,caddr ,caddrlen) ;
- 服务程序调用accept函数从处于监听状态的流套接字sd的客户连接请求队列中取出排在最前的一个客户请求, 并且创建一个新的套接字来与客户套接字创建连接通道
- 仅用于TCP套接字
- 仅用于服务器
- 利用新创建的套接字(newsock)与客户通信
- send, sendto
send (sd , *buf ,len ,flags) ;
sendto (sd , *buf ,len , flags ,destaddr ,addrlen);
- send函数TCP套接字(客户与服务器)
或调用了
connect函数的UDP客户端套接字 - sendto函数用于UDP服务器端套接字与
未调用
connect函数的UDP客户端套接字
- recv, recvfrom
recv(sd ,*buffer ,len ,flags);
recvfrom (sd ,*buf ,len ,flags , senderaddr ,saddrlen);
- recv函数从TCP连接的另一端接收数据,或者从调用了connect函数的UDP客户端套接字接收服务器发来的数据
- recvfrom函数用于从UDP服务器端套接字与未调用connect函数的UDP客户端套接字接收对端数据
SOCKET API 函数小结
WSAStartup
: 初始化socket库(仅对WinSock)WSACleanup
: 终止socket库的使用(仅对WinSock)socket
: 创建套接字connect
: “连接”远端服务器(仅用于客户端)closesocket
: 释放/关闭套接字bind
: 绑定套接字的本地IP地址和端口号(通常客户端不需要)listen
: 置服务器端TCP套接字为监听模式,并设置队列大小(仅用于服务器端TCP套接字)accept
: 接受/提取一个连接请求,创建新套接字,通过新套接(仅用于服务器端的TCP套接字)recv
: 接收数据(用于TCP套接字或连接模式的客户端UDP套接字)recvfrom
: 接收数据报(用于非连接模式的UDP套接字)send:发送数据(用于TCP套接字或连接模式的客户端UDP套接字)sendto
: 发送数据报(用于非连接模式的UDP套接字)setsockopt
: 设置套接字选项参数getsockopt
: 获取套接字选项参数
关于网络字节顺序
- TCP/IP定义了标准的用于协议头中的二进制整数表示:网络字节顺序(network byte order)
- 某些Socket API函数的参数需要存储为网络字节顺序(如IP地址、端口号等)
- 可以实现本地字节顺序与网络字节顺序间转换的函数
htons
: 本地字节顺序→网络字节顺序(16bits)ntohs
: 网络字节顺序→本地字节顺序(16bits)htonl
: 本地字节顺序→网络字节顺序(32bits)ntohl
: 网络字节顺序→本地字节顺序(32bits)
网络应用的Socket API(TCP)调用基本流程
客户端解析IP+端口号
解析服务器IP地址
- 客户端可能使用域名(如:study.163.com)或IP地址(如:123.58.180.121)标识服务器
- IP协议需要使用32位二进制IP地址
- 需要将域名或IP地址转换为32位IP地址
- 函数 inet_addr() 实现点分十进制IP地址到32位IP地址转换
- 函数 gethostbyname() 实现域名到32位IP地址转换
- 返回一个指向结构
hostent
的指针
- 返回一个指向结构
解析服务器(熟知)端口号
- 客户端还可能使用服务名(如HTTP)标识服务器端口
- 需要将服务名转换为熟知端口号
- 函数getservbyname( )
- 返回一个指向结构servent的指针
- 函数getservbyname( )
解析协议号
- 客户端可能使用协议名(如:TCP)指定协议
- 需要将协议名转换为协议号(如:6)
- 函数getprotobyname ( )实现协议名到协议号的转换
- 返回一个指向结构
protoent
的指针
- 返回一个指向结构
- 函数getprotobyname ( )实现协议名到协议号的转换
通信流程
TCP客户端软件通信流程
- 确定服务器IP地址与端口号
- 创建套接字
- 分配本地端点地址(IP地址+端口号)
- 连接服务器(套接字)
- 遵循应用层协议进行通信
- 关闭/释放连接
UDP客户端软件流程
- 确定服务器IP地址与端口号
- 创建套接字
- 分配本地端点地址(IP地址+端口号)
- 指定服务器端点地址,构造UDP数据报
- 遵循应用层协议进行通信
- 关闭/释放套接字
4种类型基本服务器
- 循环无连接(Iterative connectionless)服务器
- 循环面向连接(Iterative connection-oriented)服务器
- 并发无连接(Concurrent connectionless)服务器
- 并发面向连接(Concurrent connection-oriented)服务器
- 循环无连接服务器基本流程
- 创建套接字
- 绑定端点地址(INADDR_ANY+端口号)
- 反复接收来自客户端的请求
- 遵循应用层协议,构造响应报文, 发送给客户
数据发送
- 服务器端不能使用
connect()
函数 - 无连接服务器使用
sendto()
函数发送数据报
获取客户端点地址
- 调用
recvfrom()
函数接收数据时,自动提取
- 循环面向连接服务器基本流程
- 创建(主)套接字,并绑定熟知端口
- 设置(主)套接字为被动监听模式,准备用于服务器;
- 调用accept()函数接收下一个连接请求(通过主套接字),创建新套接字用于与该客户建立连接;
- 遵循应用层协议,反复接收客户请求, 构造并发送响应(通过新套接字);
- 完成为特定客户服务后,关闭与该客户之间的连接,返回步骤3.
- 并发无连接服务器基本流程
主线程1: 创建套接字,并绑定熟知端口号
主线程2: 反复调用 recvfrom()
函数,接收下一个客户请求, 并创建新的子线程处理该客户响应;
子线程1: 接收一个特定请求;
子线程2: 依据应用层协议构造响应报文,并调用 sendto()
发送;
子线程3: 退出(一个子线程处理一个请求后即终止)。
注意:多个子线程和一个主线程可能 同时运行
- 并发面向连接服务器基本流程
主线程1: 创建(主)套接字,并绑定熟知端口号;
主线程2: 设置(主)套接字为被动监听模式,准备用于服务器;
主线程3: 反复调用 accept()
函数接收下一个连接请求(通过主套接字),并创建一个新的子线程处理该客户响应;
子线程1: 接收一个客户的服务请求(通过新创建的套接字);
子线程2: 遵循应用层协议与特定客户进行交互;
子线程3: 关闭/释放连接并退出(线程终止).