应用层的学习内容大致有如下,最重要的内容是几个网络协议:
网络应用与单机应用有哪些本质性的不同?最直白的回答是:网络应用要联网才能用!一部分软件跑在我们的主机上,有的软件跑在远端数据库上,两者交互才有了我们所使用的网络应用。
网络该采取什么样的体系结构?
- 客户机/服务器结构(C/S):服务器提供24小时服务和永久性访问的地址/域名,利用大量服务器实现可拓展性,能同时请求用户大量的并发请求。客户机与服务器通信,使用服务器提供的服务,间歇性、有需求地接入网络,可能使用动态IP地址。客户机不会与其他客户机直接通信。Web就是C/S例子:
-
点对点结构(P2P):不是永久在线的服务器,任意端系统/节点之间可以直接通讯,彼此连接的多台计算机之间都处于对等的地位。节点是间歇性接入网络的,节点可能改变自己的IP地址。
-
混合结构(Hybrid):将上面两种结构混合在一起使用,典型例子是Napster,文件传输使用P2P结构,文件的搜索采用C/S结构。每个节点向中央服务器登记自己内容,告诉服务器我有什么内容,或者提交查询请求,查找感兴趣的内容。
网络应用进程通信
进程是主机上运行的程序,同一主机上的进程通过进程间通信机制交流,由操作系统提供调用。不同主机上运行的进程通过消息交换/报文交换进行交流。客户机进程是发起通信的进程,服务器进程是等待通信请求的进程。要是和外面的花花世界产生联系,我们运行在PC端的网络应用进程是需要和互联网某个角落的进程进行通信。
套接字:Socket
这是操作系统提供的抽象,是传输基础设施向进程提供的API。进程间通信利用socket来使用下层的协议栈进行发送/接收消息。
寻址进程
不同主机上的进程通信,每个进程必须拥有标识符。IP地址唯一标识Internet的主机。首先通过IP地址寻址主机,再通过端口号定位主机上的进程,主机每一个需要通信的进程都会被分配的一个端口号。有些端口号是固定的,如HTTP Server使用80端口,Mail Server使用 25端口。
进程的标识符是IP地址+端口号。
应用层协议
网络应用需要遵循应用层协议。公开协议由RFC定义,允许互操作,常见的应用层协议有HTTP、SMTP,研究这些协议文档可以到RFC上学习。还有私有协议,是多数P2P文件共享应用所使用。
应用层协议的内容主要有:
- 消息类型:请求/响应消息
- 消息的语法/格式:包括许多字段
- 字段的语义
- 规则:进程如何/何时发送/响应消息
网络应用的需求
关于数据丢失、可靠性方面,有的网络应用可以容忍一定的数据丢失,比如网络电话、看视频,卡一点无所谓,但是向某些应用要求100%可靠的数据传输,如文件传输、telnet。
关于时间延迟方面,有些应用只有在延迟足够低时才“有效”,比如打游戏。
关于带宽方面,某些应用只有在带宽达到最低要求时才“有效”,如网络视频,某些应用能够适应任何带宽,比如email。
Internet提供的传输服务
Internet提供两类传输服务。一个是TCP,一个是UDP。TCP是面向连接的服务,这个连接是全双工的,它是可靠的,能把底层的不可靠转为可靠的。UDP是无连接的,它做了任何一个传输层服务必须要做的基本事件,虽然简单,但是给我们提供了最基本的服务和掌控自由。
典型网络应用所使用的传输层服务有:
思考:盘点你计算机上的网络应用,所采用的名字、功能、协议等,分析使用的传输服务是TCP还是UDP?
我的回答:QQ既有UDP也有TCP!QQ采用的通信协议以UDP为主,辅以TCP协议。QQ客户端之间的消息传送主要采用了UDP模式,因为用户实在太多了,使用UDP的好处就是传输高效、占用资源少。为了解决UDP的不可靠问题,腾讯采用上层协议来保证可靠传输,如果客户端使用UDP协议发出消息后,服务器收到该包,需要使用UDP协议发回一个应答包。如此来保证消息可以无遗漏传输。之所以会发生在客户端明明看到“消息发送失败”但对方又收到了这个消息的情况,就是因为客户端发出的消息服务器已经收到并转发成功,但客户端由于网络原因没有收到服务器的应答包引起的。
Web与HTTP
Web有很多网页,这些网页互相连接。网页又包含多个对象,包括HTML文件、JPEG图片、视频文件、动态脚本等待。这些web对象的寻址通过URL标识(RFC1738)。默认省略http。
HTTP协议(超文本传输协议)
万维网需要HTTP遵循超文本传输协议。HTTP协议采用的是C/S结构,客户(浏览器)负责请求、接收和解析展示web对象。服务器负责响应客户的请求,生成响应消息,发送响应对象。
HTTP使用的传输层协议是TCP传输协议:服务器在80端口等待客户的请求,浏览器发起到服务器的TCP链接(创建套接字Socket),服务器接收来自浏览器的TCP连接,浏览器(HTTP)与Web服务器(HTTP服务器)交换HTTP消息,完毕后关闭TCP连接。
HTTP是个无状态协议,服务器不维护任何有关客户端过去所发的请求消息。有状态的协议往往更加复杂,需要维护状态(历史信息)。一旦客户或服务器失效,会产生状态的不一致,解决这种不一致代价高。假设用无状态协议,服务器部不维护任何有关客户端过去所发请求的信息,就方便一点。
HTTP连接
HTTP连接类型分为持久性连接和非持久性连接。非持久性连接每个TCP连接最多允许传输一个对象。持久性连接中每个TCP连接允许传输多个对象。HTTP1.1版本及后默认使用持久性连接。以下是非持久性连接的例子:
我们把从客户端发送一个很小的数据包到服务器并返回所经历的时间称为RTT(Round Trip Time)。非持久性连接里,总的响应时间Total=2RTT+文件发送时间:
- 发起、建立TCP连接:1个RTT
- 发送HTTP请求消息到HTTP响应消息的前几个字节到达:1个RTT
- 发送文件所需时间
由于HTTP协议无状态,就像上面的例子,每张图片的请求都要建立一个HTTP请求,很麻烦,所以才有了持久性连接。持久性连接细分的话,又分为无流水的持久性连接、带有流水机制的持久性连接。
HTTP请求消息和响应消息
HTTP协议有两类消息,分别是请求消息和响应消息。
请求消息里,第一行是请求行,下面几行是头部行,再遇到一行空行,表示请求消息结束了。
常见的请求方法有POST方法和GET方法。POST方法是在请求消息的消息体(entity body)中上传客户端的输入,GET方法输入信息通过request行的URL字段上传。
HTTP响应消息中,第一行称为状态行,HTTP响应状态代码位于响应消息的第一行,常见的有200OK,301Moved Permanently,400Bad Request,404Not Found,505HTTP Version Not Supported。下面几行是响应头消息,再遇到一行空行,还有返回的数据信息。
体验HTTP可以可以利用telnet登录到某个Web服务器。
Cookie技术
HTTP是无状态的,但是很多应用需要服务器掌握客户端的状态,如网上购物车等,所以引入Cookie技术。Cookie技术是某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过了加密)(RFC6265)。运用Cookie就能够进行身份验证、购物车、推荐等功能。
Cookie是架设在HTTP上的组件,所以:
- HTTP响应消息加上cookie头部行
- HTTP请求消息加上cookie头部行
- 保存在客户端主机上的cookie文件,由浏览器管理
- Web服务器端要有后台数据库
上面的例子是一个新用户第一次访问该服务器,服务器会生成一个ID,存储到数据库里,并在响应行里多加一条Set-cookie:1678
。浏览器把这一行解析出来,增加到本地的Cookie文件里,再次请求的时候会增加一行请求行cookie:1678Cookie
。
当然,cookie能够被用于收集隐私、截取cookie冒充用户等问题。
Web缓存/代理服务器技术
该技术可以在不访问服务器的前提下满足客户端的HTTP请求,这样能缩短客户请求的响应时间;减少机构/组织的流量;在大范围内(Internet)实现有效的内容分发。
用户/浏览器向缓存/代理服务器发送所有的HTTP请求,如果所请求的对象在缓存中,就返回缓存对象,否则,缓存服务器向原始服务器发送HTTP请求,获取对象,然后返回给客户端并缓存该对象。
所以,缓存服务器既充当客户端,又充当服务器。一般由ISP(Internet服务提供商)架设。
HTTP有条件性GET方法,利用HTTP请求消息中声明所持有的版本的日期if-modified-since: <date>
,如果缓存的版本不是最新的版本,需要重新发送请求对象。如果不需要更新,响应消息中会返回304 Not Modified。
Email应用
该应用**依赖TCP进行Email消息的可靠传输,是占用服务器的25号端口。**Email消息只包含7位ASCII码。**使用SMTP协议,是持久性连接。**与HTTP比,HTTP是拉式(pull),把网页拉回本地、每个对象封装在独立的响应消息中,而SMTP是退式(push)把消息推给用户、多个对象在由多个部分构成的消息中发送。两协议都使用命令/响应交互模式,命令和状态代码都是ASCII码。
Email应用的构成:
- 邮件客户端:能读、写Email消息,与服务器交互,收、发Email消息,位于Web客户端。
- 邮件服务器:有个邮箱,存储发给该用户的Email;有个消息队列,存储等待发送的Email。这样能保证用户任何时候都能发邮件或者收邮件
- SMTP协议:是邮件服务器之间传递消息所使用的协议。可配合MIME,多媒体邮件拓展。
发的时候使用STMP协议,邮件服务器之间发送邮件也是使用STMP协议,但是收件人还需要邮件访问协议才能从服务器获取邮件:
- POP协议:如果是“下载并删除”模式,用户如果换了客户端软件,无法重读该邮件;如果是“下载并保持”模式,不同客户端都可以保留消息的拷贝。POP3是无状态的。
- IMAP协议:拥有更多功能,能够操纵服务器上存储的消息。消息统一保存在一个地方——服务器,允许用户利用文件夹组织消息,IMAP支持跨会话(Session)的用户状态,服务器会将文件夹与消息ID之间做映射,所以是个有状态协议。
- HTTP:163,QQ,Mail等
DNS应用
DNS是解决Internet上主机/路由器的识别问题。日常生活中,我们常常使用域名去访问网页,而不是IP地址。
域名解析系统(DNS)也是应用层协议,是多层命名服务器构成的分布式数据库,应用层协议负责完成名字的解析,属于Internet的核心功能。DNS提供域名向IP地址的翻译。
DNS可以提供的功能:能够将域名翻译成IP地址;为主机起别名;邮件服务器别名;负载均衡(当进行IP地址翻译时,可以提供多个映射,给出多个Web服务器的IP地址,这些地址轮流出现第一名,轮流被访问)。
- DNS根域名服务器:当本地域名解析服务器无法解析域名时,会访问根域名服务器,根域名要是还不知道就访问权威域名服务器,获得映射,向本地域名服务器返回映射。全球有13个根域名服务器。
- TLD顶级域名服务器:负责com,org,net,eud等顶级域名和国家顶级域名,如cn,uk,fr等~
- 权威域名服务器:组织的域名解析服务器,提供组织内部服务器的解析服务。
- 本地域名解析服务器:不严格属于层级体系,每个ISP有一个本地域名服务器。当用户进行DNS查询时,查询被发送到本地域名服务器,它将作为代理,将查询转发给(层级式)域名解析服务器系统。
DNS查询又分为迭代查询和递归查询。
为了高效查询,本地域名服务器常缓存顶级域名服务器的映射,只要域名解析服务器获得域名——IP映射,就缓存这一映射。一段时间过后,缓存条目会失效删除。
DNS资源记录
DNS数据库里的资源记录如下图,资源记录就是个四元组。不同类型的Name和Value是不同的。Type=A是最基本的主机到IP地址的映射;Type=NS指明这个域的域名解析服务器是什么;Type=CNAME是别名到真实域名的映射;Type=MX是应用于邮件服务的。
如何注册域名?
思考:我国没有根域名服务器,是否会影响我国的网络安全?https://www.33yd.com/idcnews/891.html
P2P应用
P2P架构的特点:没有服务器,任意端系统之间可以直接通信,节点阶段性接入Internet,节点可能更换IP地址。
思考:从文件分发角度看,C/S应用和P2P应用中,从一个服务器向N个节点分发一个文件,性能哪个更好?
答:如果采用C/S架构,花费的时间是线性增长的。而P2P架构是总会趋于一个平稳的值,明显低于C/S,当节点数目增大,时间不会太多增长。所以现在的下载应用广泛的使用P2P应用。
BitTorrent是使用P2P进行文件分发的典型应用。
比特流(BitTorrent)是一种内容分发协议,由布拉姆·科恩自主开发。它采用高效的软件分发系统和点对点技术共享大体积文件(如一部电影或电视节目),并使每个用户像网络重新分配结点那样提供上传服务。
如图所示,tracker相当于管理者。文件被划分为256KB的chunk,节点加入torrent时,本来没有chunk的,但是会慢慢累积,它会向tracker注册以获得节点清单,与清单的某些节点(“邻居”)建立连接。节点自己下载的同时,需要向其他节点上传chunk,大家互相共享。当节点获得了需要的文件后,可能就离开了。任何时候,节点都是动态地加入或离开的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MWfgUFkH-1623315311610)(D:\QQiBlog\博客文章\慕课大学计算机网络课程\50BitTorrent.png)]
在获取chunk的时候,给定任意时刻,不同的节点持有文件的不同chunk集合,节点会定期查询每个邻居所持有的chunk列表。当节点要主动发送特定查询请求获取缺失的chunk时,会把chunk的拥有者少的那份先请求回来。免得这些节点离开了就请求不到了。
在发送chunk时,节点会选取和它建立连接最快的4个节点发送chunk,每10秒重新评估top4。总结说,你的上传速率越高,越能找到更好的交易伙伴,更快地获取文件。
P2P索引技术
P2P系统的索引:是信息到节点位置(IP地址+端口号)的映射。
文件共享/分发:
- 利用索引动态跟踪节点所共享的文件的位置
- 节点需要告诉索引它拥有哪些文件
- 节点搜索索引,从而获知能够得到哪些文件
即时消息(QQ)
- 索引负责将用户名映射到具体位置
- 当用户名开启IM应用(即时通讯软件)时,需要通知索引它的位置
- 节点检索索引,确定用户的IP地址
集中式索引
Napster最早采用这种设计。这种设计里会有一个中央目录服务器,任何节点加入,都会通知中央服务器它的IP地址和它的内容。当某个节点要查找内容,直接找中央服务器,服务器告诉它谁有这个文件,这个节点就会直接连上拥有这个文件的节点,也就是P2P的应用啦~
这个设计的问题就是由于内容和文件传输是分布式的,但是内容定位是高度集中式的,当中央目录服务器挂了,会存在单点失效问题、大量请求导致性能瓶颈问题、因版权问题受举报打击。
分布式索引系统:洪泛式查询
采用完全分布式架构,文件共享网络Gnutella采用这种架构,每个节点对它共享的文件进行索引服务,且只对它共享的文件进行索引。没了中央服务器,该怎么寻找需要的文件呢?就靠洪泛式查询了,发出查询的节点通过已有的TCP连接向连接上的节点发送查询消息,接收查询消息的节点会转发给它对应连接上的节点,一次次转发查询直至查询命中,就反向路径发回给查询节点。
缺点是会给网络带来很大的负担。
层次式覆盖网络
第三种索引方案是介于集中式索引和洪范查询之间的方法,每个节点可能是一个超级节点,也可能是一个被分配一个超级节点的普通节点,这些节点间维持TCP连接。超级节点负责跟踪子节点的内容,为子节点提供索引服务。超级节点之间再使用洪泛式查询。
P2P案例应用:Skype
Skype是一款即时通讯软件,其具备IM所需的功能,比如视频聊天、多人语音会议、多人聊天、传送文件、文字聊天等功能。它的本质上是P2P的应用,用户和节点对之间直接通信;使用私有应用层协议,所以我们不知道内部的具体实现逻辑。采用层次式覆盖网络架构;索引负责维护用户名与IP地址间的映射,索引分布在超级节点上。
Socket编程-应用编程接口(API)
现如今,我们想开发一个网络程序应用,有哪些方式?比如直接网卡编程,再或者屏蔽网卡细节的基于Packet Driver编程,Windows提供的基于NDIS网络编程;基于各种函数库LibPcap/WinPcap编程;会话层用NetBIOS编程等等…还有一个重点就是应用层和传输层之间提供的应用程序接口——套接字。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZXP1gEcr-1623315311611)(D:\QQiBlog\博客文章\慕课大学计算机网络课程\51网络程序设计接口.png)]应用编程接口API(Application Programming Interface):就是应用进程的控制权和操作系统的控制权进行转换的一个系统调用接口。每个端系统可以看作是一个五层结构的小系统,不同端的应用层里的应用进程交流需要遵循应用层协议,但是它绝对不是直接从我的应用层“飞”去另一个应用层,而是要过一遍5层网络结构,所以套接字一般值应用层和它的相邻层——传输层的接口。通过这个接口,应用层的数据就可以交给下一层了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6OAxcyqn-1623315311612)(D:\QQiBlog\博客文章\慕课大学计算机网络课程\52应用程序设计接口.png)]
几种典型的应用编程接口:
- Berkeley UNIX操作系统定义了一种API,称为套接字接口(socket interface),简称套接字(socket),也是现在应用最广泛的。
- 微软公司在其操作系统中采用了套接字接口API,形成了一个稍有不同的API,并称之为Windows Socket Interface,WINSOCK。
- AT&T为其UNIX系统V定义了一种API,简写为TLI
Socket API
套接字API最初是面向TCP/IP协议栈的接口,目前绝大多数操作系统都支持。给我们提供了开发C/S应用的很好的手段,是应用进程间通信的抽象机制。
问题来了,我怎么知道我对外要和哪一个服务器套接字进行交流?
答:首先想到IP地址,但是可能有多个套接字,所以我们给套接字个号码,也就是我们常说的端口号,总结来说,套接字对外唯一标识通信端点的方式:IP地址+端口号。
第二个问题,操作系统/进程(对内)如何管理那么多的套接字?
我的答案:通过套接字描述符。属于一种Socket抽象,类似于文件的抽象,把套接字看作一种特殊文件。当应用进程创建套接字时,操作系统分配一个数据结构存储该套接字相关信息,创建套接字后会返回套接字描述符。在管理套接字时,都是在使用这个描述符进行管理或引用。
在套接字API里定义了地址结构sockaddr_in,包括IP地址和端口号,还有地址组等等。使用TCP/IP协议簇的网络应用程序声明端点地址变量(赋AF_INET)时,使用结构sockaddr_in。
地址结构:
struct sockaddr_in
{
u_char sin_len; /*地址长度 */
u_char sin_family; /*地址族(TCP/IP:AF_INET) */
u_short sin_port; /*端口号 */
struct in_addr sin_addr; /*IP地址 */
char sin_zero[8]; /*未用(置0) */
}
一些Socket API函数(WinSock):WSAStartup(初始化Windows Sockerts API)-> 应用程序 -> WSACleanup(释放所使用的Windows Sockets DLL)
-
WSAStartup:使用Socket的应用程序在使用Socket之前必须首先调用WSAStartup函数。主要有两个参数。
-
WSACleanup函数:应用程序在完成对请求的Socket库的使用,最后要调用WSACleanup函数来解除与Socket库的绑定,释放Socket库所占用的系统资源。
-
Closesocket函数:关闭一个描述符为sd的套接字,如果多个进程共享一个套接字,调用closesocket将套接字引用计数减1,减至0才关闭。如果进程中的一个线程调用closesocket将一个套接字关闭,该进程中的其他线程也将不能访问该套接字。
// 调用格式 int closesocket(SOCKET sd); 返回值:0:成功 ;SOCKET_ERROR:失败
-
connect函数:客户程序调用connect函数来使客户套接字(sd)与特定计算机的特定端口(saddr)的套接字(服务)进行连接(用于TCP建立连接),用于客户端,既可用于TCP客户端也可以用于UDP客户端。
-
bind函数:绑定套接字的本地端点地址:IP地址+端口号。
int bind(sd, localaddr, addrlen);
-
还有好多Socket API阿~~那就直接看看网络应用的Socket API(TCP)调用基本流程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a89WYHt5-1623315311613)(D:\QQiBlog\博客文章\慕课大学计算机网络课程\53Socket API.png)]
在通讯过程中,客户端与服务端通信,最先发起API调用的是服务端。在WinSock环境下,先调用的是WSAStartup函数,初始化Windows Sockerts API;socket函数创建套接字;bind函数为套接字绑定端点地址,作为TCP服务器套接字;调用listen函数,启动监听,指定队列长度;接着,调用accpet函数(阻塞函数)来接收客户端的请求。
接着看客户端,最先调用的也是WSAStartup函数,socket函数创建客户端套接字,接下来客户端调用connect函数(阻塞函数),调用成功后,客户端就与服务器发生联系了~
accept接收到connect函数的连接请求,就创建一个新的套接字与客户端进行连接确认。服务器以后也会用这个新套接字接收客户端的请求(recv),客户端也会通过该套接字发送请求(send)。反过来,客户端接收服务端通信也同理。
最后通信结束了,双方都会调用closesocket函数。
网络字节顺序转换函数
TCP/IP定义了标准的用于协议头中的二进制整数表示:网络字节顺序。某些Socket API函数的参数需要存储为网络字节顺序(如IP地址、端口号等),假如用了和网络字节顺序不一样的本地字节顺序,那就出错了。
可以实现本地字节顺序与网络字节顺序间转换的函数:
- htons: 本地字节顺序→网络字节顺序(16bits)
- ntohs: 网络字节顺序→本地字节顺序(16bits)
- htonl: 本地字节顺序→网络字节顺序(32bits)
- ntohl: 网络字节顺序→本地字节顺序(32bits)
Socket编程——客户端软件设计
解析服务器IP地址
客户端使用域名或IP地址标识服务器,IP协议需要使用32位二进制IP地址。客户端需要将域名或IP地址转换位32位IP地址,可以调用两个函数,得到的是网络字节顺序,就可以直接向套接字API传递参数:
- 函数inet_addr( ) 实现用户输入的点分十进制IP地址到32位IP地址转换
- 函数gethostbyname( ) 实现用户输入的域名解析/映射到32位IP地址转换,返回一个指向结构hostent 的指针
解析服务器(熟知)端口号
客户端没直接给出指定的端口号,比如可能使用服务名(如HTTP)标识服务器端口,所以需要将服务名转换为熟知端口号。
- 函数getservbyname( ),返回一个指向结构servent的指针
解析协议号
所以协议都利用协议号进行标识,客户端可能更常使用协议名(如:TCP)指定协议,所以客户端软件需要调用函数将协议名转换为协议号(如:6)。
- 函数getprotobyname ( ) 实现协议名到协议号的转换
TCP软件客户端软件流程
- 确定服务器IP地址与端口号
- 创建客户端本地套接字
- 为创建的套接字后自动分配本地端点地址(IP地址+端口号)
- 连接服务器(套接字)
- 遵循应用层协议进行通信
- 通信结束后,客户端关闭/释放连接
UDP客户端软件流程
- 确定与之通信的服务器IP地址与端口号
- 创建UDP客户端套接字
- 分配本地端点地址(IP地址+端口号)
- 指定服务器端点地址,UDP不是面向连接的,构造UDP数据报
- 遵循应用层协议进行通信
- 关闭/释放UDP套接字
Socket编程——服务器软件设计
4种类型基本服务器:
循环无连接:一次只处理一个客户的服务请求,顺序处理,非并发的。
- 创建UDP套接字
- 绑定端点地址(INADDR_ANY+端口号)
- 反复通过套接字接收来自客户端的请求
- 遵循应用层协议,构造响应报文,发送给客户
循环面向连接
- 创建(主)套接字,并绑定熟知端口号;
- 设置(主)套接字为被动监听模式,准备用于服务器;
- 调用accept()函数接收下一个连接请求(通过主套接字),创建新套接字用于与该客户建立连接;
- 遵循应用层协议,反复接收客户请求,构造并发送响应(通过新套接字);
- 完成为特定客户服务后,关闭与该客户之间的连接,返回步骤3.
并发无连接
- 主线程第1步: 创建套接字,并绑定熟知端口号;
- 主线程第2步: 反复调用recvfrom()函数,接收下一个客户请求,并创建新线程处理该客户响应;
- 子线程第1步: 接收一个特定请求;
- 子线程第2步: 依据应用层协议构造响应报文,并调用sendto()发送;
- 子线程第3步: 退出(一个子线程处理一个请求后即终止)。
并发面向连接:同时为多个用户服务
- 主线程第1步: 创建(主)套接字,并绑定熟知端口号;
- 主线程第2步: 设置(主)套接字为被动监听模式,准备用于服务器;
- 主线程第3步: 反复调用accept()函数接收下一个连接请求(通过主套接字),并创建一个新的子线程处理该客户响应;也就是主套接字不会向客户端返回响应,只接受连接请求。
- 子线程第1步: 接收一个客户的服务请求(通过新创建的套接字);
- 子线程第2步: 遵循应用层协议与特定客户进行交互;
- 子线程第3步: 子线程服务结束,关闭/释放连接并退出(线程终止)
参考:百度百科——对等网络
mooc大学计算机网络