连接_连接mysql - CSDN
  • 先给出两张表:一、内连接: 内连接(INNER JOIN):有两种,显式的和隐式的,返回连接表中符合连接条件和查询条件的数据行。(所谓的链接表就是数据库在做查询形成的中间表)。1、等值连接 概念:在连接条件中...

    先给出两张表:


    一、内连接:

        内连接(INNER JOIN):有两种,显式的和隐式的,返回连接表中符合连接条件和查询条件的数据行。(所谓的链接表就是数据库在做查询形成的中间表)。

    1、等值连接

         概念:在连接条件中使用等于号(=)运算符,其查询结果中列出被连接表中的所有列,包括其中的重复列。

    例子:

    select  * 

    from T_student s,T_class c 

    where s.classId = c.classId

    等价于

    select  * 

     from T_student s inner join T_class c on s.classId = c.classId

    2、不等连接

       概念:在连接条件中使用除等于号之外运算符(>、<、<>、>=、<=、!>和!<)

    select * from T_student s inner join T_class c on s.classId <> c.classId

    二、外连接

        外连接分为左连接(LEFT JOIN)或左外连接(LEFT OUTER JOIN)、右连接(RIGHT JOIN)或右外连接(RIGHT OUTER JOIN)、全连接(FULL JOIN)或全外连接(FULL OUTER JOIN)。我们就简单的叫:左连接、右连接和全连接。

    1、左连接:

        概念:返回左表中的所有行,如果左表中行在右表中没有匹配行,则结果中右表中的列返回空值。

    例如:

    select  *

    from T_student s left join T_class c on s.classId = c.classId

    检索结果:

      总结:左连接显示左表全部行,和右表与左表相同行。

    2、右连接:

       概念:恰与左连接相反,返回右表中的所有行,如果右表中行在左表中没有匹配行,则结果中左表中的列返回空值。

    例如:

         select * from  T_student s right join T_class c on s.classId = c.classId

    检索结果:

     总结:右连接恰与左连接相反,显示右表全部行,和左表与右表相同行。

    3、全连接:

      概念:返回左表和右表中的所有行。当某行在另一表中没有匹配行,则另一表中的列返回空值。

         select * from  T_student s full join T_class c on s.classId = c.classId

       总结:返回左表和右表中的所有行。

    三、交叉连接(CROSS JOIN):也称迪卡尔积

    概念:不带WHERE条件子句,它将会返回被连接的两个表的笛卡尔积,返回结果的行数等于两个表行数的乘积(例如:T_student和T_class,返回4*4=16条记录),如果带where,返回或显示的是匹配的行数。

    1、不带where:

    1.    select *from T_student cross join T_class    //cross join 可以省略不写
    2.   等于
    3.    select *from T_student, T_class
    总结:相当与笛卡尔积,左表和右表组合。

    2、有where子句,往往会先生成两个表行数乘积的数据表,然后才根据where条件从中选择。

    1. select * from T_student s cross join T_class c where s.classId = c.classId   
    2.    (注:cross join后加条件只能用where,不能用on)  
          查询结果跟等值连接的查询结果是一样。


    展开全文
  • 连接和短连接

    2019-03-04 15:51:40
    https://www.cnblogs.com/gotodsp/p/6366163.html
    展开全文
  • TCP连接

    2018-05-24 15:48:55
    简述TCP是面向连接的协议,TCP把连接作为最基本的抽象。每一条TCP连接唯一地被通信两端的两个端点所确定。那么,TCP连接的端点是什么呢?TCP连接的端点又叫套接字(socket),根据TCP协议的规定,端口号拼接到IP地址...

    简述

    TCP是面向连接的协议,TCP把连接作为最基本的抽象。每一条TCP连接唯一地被通信两端的两个端点所确定。那么,TCP连接的端点是什么呢?TCP连接的端点又叫套接字(socket),根据TCP协议的规定,端口号拼接到IP地址即构成了套接字,即

    套接字 socket = (IP地址:端口号)

    这样一来,TCP连接可以以下式子表示

    TCP连接 ::= {socket1, socket2} = {(IP1: port1),(IP2: port2)}

    在面向连接通信中,连接的建立和释放是必不可少的过程。TCP连接的建立采用客户服务器方式,主动发起连接建立的应用进程叫做客户,而被动等待连接的应用进程叫做服务器。 
    本文主要讲述TCP是如何管理连接的建立和连接的释放的。

    TCP的连接建立

    三次握手建立TCP连接
    图1:三次握手建立TCP连接

    图1画出了TCP连接建立的过程。假定图中左端是客户A,右端是服务器B,一开始时,两端都处于CLOSED(关闭)状态。图中的方框分别是端点所处的状态。 
    1)服务器进程准备好接受外来的连接,这通常是通过调用socket,bind,listen这三个函数来完成,我们称之为被动打开(passive open)。然后服务器进程就处于LISTEN状态,等待客户的连接请求,如有,则作出响应。 
    2)客户通过调用connect发起主动打开(active open),向服务器发出连接请求报文段,请求中的首部的同步位SYN = 1,同时选择一个初始序号seq = x。TCP规定,SYN报文段不能携带数据,则要消耗一个序号。 
    这时,TCP客户进入SYN-SEND(同步已发送)状态。

    TCP规定,首部中序号字段值是本报文段所发送数据的第一个字节的序号。

    3)服务器收到客户端连接请求后,必须确认(ACK)客户的SYN报文段。在确认报文段中,把SYN和ACK位都置为1,确认号为ack = x + 1,同时也为自己选择一个初始序号seq = y。请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号。 
    这时,TCP服务器进入SYN-RCVD(同步收到)状态。

    TCP规定,若确认号 = N,则表明:到序号 N - 1为止的所有数据都已正确收到。

    4)客户在收到服务器的确认后,还要向服务器进程给出确认。确认报文段的ACK置1,确认号ack = y + 1,而自己的序号seq = x + 1。TCP规定,这个报文段可以携带数据,也可以不携带数据,如果不携带数据,下一个数据报文段的序号仍是seq = x + 1。 
    这时,TCP连接已经建立,客户进入ESTABLISHED(已建立连接)状态。 
    5)服务器收到客户的确认后,也进入ESTABLISHED状态。 
    在上述的建立连接的过程中,前后发送了三个报文段,因此TCP建立连接的过程也称之为三次握手(three-way handshake)。

    为什么需要三次握手

    为什么客户在收到服务器的确认后,还要向服务器发送一次确认呢?这主要是为了防止已失效的连接请求报文段突然又传送到了服务器,因而发生错误。 
    考虑一种情况,客户发出连接请求后,但因连接请求报文丢失而未收到确认。于是客户再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接。客户共发送了两个连接请求报文段,其中第一个丢失,第二个到达了服务器。没有“已失效的连接请求报文段”。 
    现假定一种异常情况。即客户发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达服务器。本来这是一个早已失效的报文段,但服务器收到此失效的连接请求后,就误认为是客户又一次发出一次新的连接请求。于是就向客户发出确认报文段,同意建立连接。假定不采用三次握手,那么只要服务器发出确认,新的连接就建立了。 
    由于现在客户端并没有发出建立连接的请求,因此不会理睬服务器的确认,也不会向服务器发送数据。但服务器却以为新的连接已经建立了,并一直等待客户发送数据。服务器的许多资源就这样白浪费了。 
    采用三次握手的办法可以防止上述现象的发生。例如刚才的情况下,客户不会向服务器的确认发出确认,由于服务器收不到确认,就知道客户并没有要求建立连接。

    TCP的连接释放

    TCP建立一个连接需要三个报文段,释放一个连接却需要四个报文段。 
    TCP释放连接的过程
    图2:TCP释放连接的过程

    数据传输结束后,通信的双方可以释放连接。数据传输结束后的客户A和服务器B都处于ESTABLISHED状态,然后进入释放连接的过程。 
    1)A的应用进程先发出释放连接报文段,并停止发送数据,主动关闭TCP连接。A把连接释放报文段首部FIN置1,其序号为seq = u。这时A进入FIN-WAIT-1(终止等待1)状态。 
    2)B收到连接释放报文段后即发出确认确认号为ack = u + 1,而自己的序号为seq = v。然后B就进入CLOSE-WAIT(关闭等待)状态。TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭状态,即A已经没有数据要发送了,但B若发送数据,A仍接收。 
    3)A收到来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。 
    4)若B已经没有要向A发送的数据,其应用进程就通知TCP释放 连接。这时B发出的连接释放报文段FIN = 1,还必须重复上次已发送过的确认号ack = u + 1。假定B的序号为w(在半关闭期间B可能又发送了一些数据)。这时B就进入了LAST-ACK(最后确认)状态,等待A的确认。 
    5)A收到了的连接释放报文段后,必须对此发出确认。其确认号为ack = w + 1,而自己的序号为seq = u + 1。然后进入到TIME-WAIT(时间等待)状态。请注意,现在TCP连接还没有释放掉。必须经过时间等待计时器(TIME-WAIT timer)设置的时间 2MSL后,A才进入到CLOSED状态。时间MSL叫做最长报文段寿命(Maximum Segment Lifetime)。 
    6)B只要收到A发出的确认,就进入CLOSED状态。我们注意到,B结束TCP连接的时间要比A早一些。 
    由于释放TCP连接的过程需要发送四个报文段,因此释放连接的过程也称之为四次握手。

    TIME_WAIT状态

    上述释放连接的过程中,A在TIME-WAIT状态必须等待2MSL,才进入CLOSED状态,上面也提到,这个MSL是报文段的最长寿命。那么MSL的真实含义是什么呢? 
    MSL是任何IP数据报能够在网络中存活的最长时间。我们知道这个时间是有限的,因为每个数据报含有一个称为跳限(hop limit)的8位字段,它的最大值是255,即最大为255跳。尽管这是一个跳数限制而不是真正的时间限制,我们仍然假设:具有最大跳限的数据报在网络中存在的时间不可能超过MSL秒。 
    任何TCP实现都必须为MSL选择一个值。RFC 1122的建议值为2分钟,对于现在的网络,MSL = 2分钟可能太长了,故一些实现采用30秒的值,这意味着,TIME-WAIT状态的持续时间在1分钟到4分钟之间。 
    为什么客户在TIME-WAIT状态必须2MSL的时间呢?这有两个理由: 
    1)可靠地实现TCP全双工连接的终止 
    客户A最后一个ACK报文段可能丢失,这样服务器B处于LAST-ACK状态而收不到确认。接下来B会超时重传FIN + ACK报文段,而A就能在2MSL时间内收到这个重传的FIN + ACK报文段,并再重传一次确认,并重新启动2MSL计时器。最后,A和B都正常进入CLOSED状态。 
    如果A在发送完最后一个ACK报文段后立即释放连接,那么就无法收到B重传的FIN + ACK报文段,因而也不会再发送一次确认报文段,这样B就无法按照正常步骤进入CLOSED状态。 
    2)防止“已失效的连接请求报文段”出现在本连接中 
    客户A在发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接持续的时间内所产生的所有报文段都会网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。

    后记

    有这样一道面试题,对于应用程序来说,什么情况下会出现大量 TIME_WAIT 的状态? 
    TIME_WAIT 出现的原因可以参考上面的详细解析,从上面的描述我们也可以知道,TIME_WAIT 的出现是一般是客户主动关闭 TCP 连接而出现的,即出现在客户端机器,服务端机器一般不会出现 TIME_WAIT 状态。 
    那么,在什么情况下,客户端机器会大量出现关闭 TCP 连接呢? 
    记得在网易的时候,我曾经为处理用户连接实时语音服务的日志开发过一个日志补全进程 audiolog。 
    用户每天累积的实时语音日志达1千多万条,audiolog 进程在每天的固定时间(01:30)扫描语音日志,发现某些日志如果存在字段缺失的情况,audiolog 会通过发送 HTTP 请求查询并补全字段信息,audiolog会在短时间内扫描完所有的日志并运行完毕。我们知道 HTTP 是基于 TCP 的,这就导致短时间内 audiolog 断开大量的 TCP 连接,导致大量 TIME_WAIT 状态的出现。


    图3:audiolog 机器出现 TIME_WAIT 状态统计

    由图3可以看到,audiolog 所在的机器,在01:30这个时间点,出现了大量的 TIME_WAIT 状态,这个时间点正是 audiolog 进程运行的时间点,这跟上述分析出现大量 TIME_WAIT 状态的原因是一致的。

    上述的情况,都是在客户端出现 TIME_WAIT 的情况。另外,如果服务端主动关闭客户端非法请求或者处理长时间不跳跃连接,也会在服务端机器出现 TIME_WAIT 的状态。

    展开全文
  • 客户端应用程序可以打开一条TCP/IP连接连接到可能运行在世界任何地方的服务器应用程序。一旦连接建立起来了,在客户端和服务器的计算机之间交换的报文就永远不会丢失、受损或失序。1.1、TCP的可靠数据管控 HTTP...

    1、TCP连接

            世界上几乎所有的HTTP通信都是由TCP/IP承载的。TCP/IP是全球计算机及网络设备都在使用的一种常用的分组交换网络分层协议集。客户端应用程序可以打开一条TCP/IP连接,连接到可能运行在世界任何地方的服务器应用程序。一旦连接建立起来了,在客户端和服务器的计算机之间交换的报文就永远不会丢失、受损或失序。

    1.1、TCP的可靠数据管控

            HTTP连接实际上就是TCP连接和一些使用连接的规则。TCP连接是因特网上的可靠连接。要想正确、快速地发送数据,就需要了解TCP的一些基本知识。
            TCP为HTTP提供了一条可靠的比特传输管道。从TCP连接一端填入的字节会从另一端以原有的顺序、正确地传达出来。
            Web浏览器通过TCP连接与Web服务器进行交互:


    1.2、TCP流是分段的、由IP分组传送

            TCP的数据是通过名为IP分组的小数据块来发送。这样的话,HTTP就是“HTTP over TCP over IP”这个“协议栈”中的最顶层了。其安全版本HTTPS就是在HTTP和TCP之间插入了一个密码加密层(TLS或SSL)。
            HTTP要传送一条报文时,会以流的形式将报文数据的内容通过一条打开的TCP连接按序传输。TCP收到数据流之后,会将数据流砍成被称作段的小数据块,并将段封装在IP分组中,通过因特网进行传输。所有这些工作都是由TCP/IP软件来处理的,HTTP程序员什么都看不到。
            每个TCP段都是由IP分组承载,从一个IP地址发送到另一个IP地址的。每个IP分组都包含:

    • 一个IP分组首部(通常为20字节)
    • 一个TCP段首部(通常为20字节)
    • 一个TCP数据块(0个或多个字节)

            IP首部包含了源和目的IP地址、长度和其他一些标记。TCP段的首部包含了TCP的端口号、TCP控制标记,以及用于数据排序和完整性检查的一些数字值。

    1.3、保持TCP连接的正确运行

            在任意时刻计算机都可以有几条TCP连接处于打开状态。TCP是通过端口号来保持所有这些连接的正确运行的。
            IP地址可以将你连接到正确的计算机,而端口号则可以将你连接到正确的应用程序上。TCP连接时通过4个值来识别的:
            <源IP地址、源端口号、目的IP地址、目的端口号>
            这4个值一起唯一地定义了一条连接。两条不同的TCP连接不能拥有4个完全相同的地址组件值。

    1.4、用TCP套接字编程

            操作系统提供了一些操纵其TCP连接的工具。下表显示了套接字API提供的一些主要接口:

    套接字API调用

    描述

    s = socket(<parameters>)

    创建一个新的、未命名、未关联的套接字

    bind(s,<local IP:port>)

    向套接字赋一个本地端口号和接口

    connect(s,<remote IP:port>)

    创建一条连接本地套接字与远程主机及端口的链接

    listen(s,…)

    标识一个本地套接字,使其可以合法接收连接。

    s2 = accept(s)

    等待某人建立一条到本地端口的连接

    n = read(s, buffer, n)

    尝试从套接字向缓冲区读取n个字节

    n = writer(s, buffer, n)

    尝试从缓冲区中向套接字写入n个字节

    close(s)

    完全关闭TCP连接

    shutdown(s, <side>)

    只关闭TCP链接的输入或输出端

    getsockopt(s, …)

    读取某个内部套接字配置选项的值

    setsockopt( s, …)

    修改某个内部套接字配置选项的值



             这个套接字API向HTTP程序员隐藏了TCP和IP的所有细节。套接字API最初是为Unix操作系统开发的,但现在几乎所有的操作系统和语言中都有其变体存在。套接字API允许用户常见了TCP的端点数据结构,将这些端点与远程服务器的TCP端点进行连接,并对数据流进行读写。TCP API隐藏了所有底层网络协议的握手细节,以及TCP数据流与IP分组之间的分段和重装细节。
            通过套接字API来凸显客户端和服务器在实现HTTP事务时所应执行的步骤如下:

           

            上图从Web服务器等待连接(S4)开始,客户端根据URL判定出IP地址和端口号,并建立一条道服务器的TCP连接(C3)。建立连接可能要花费一些时间,时间长短取决于服务器距离的远近、服务器的负载情况,以及因特网的拥挤程度。一旦建立了连接,客户端就会发送HTTP请求(C5),服务器则会读取请求(S6)。一旦服务器获取了整条请求报文,就会对请求进行处理,执行所请求的动作(S7),并将数据写回客户端。客户端读取数据(C6),并对响应数据进行处理(C7)。

    2、TCP性能问题

            HTTP紧挨着TCP,位于其上层,所以HTTP事务的性能在很大程度上取决于底层TCP通道的性能。

    2.1、HTTP事务的时延

            下图显示了HTTP事务主要的链接、传输以及处理演示。与建立TCP链接,以及传输请求和响应报文的时间相比,事务处理时间可能是很短的。除非客户端或服务器超载,或者正在处理复杂的动态资源,否则HTTP时延就是由TCP网络时延构成的。


            HTTP事务的时延有以下几种主要原因:
            1、客户端首先要根据URI确定Web服务器的IP地址和端口号。如果最近没有对URI中的主机名进行访问,通过DNS解析系统将URI中的主机名转换成一个IP地址可能要花费数十秒的时间。
            2、客户端向服务器发送一条TCP连接请求,并等待服务器回送一个请求接收应答。每条新的TCP连接都会有连接建立时延。这个值通常最多只要一两秒,但如果有数百个HTTP事务的话,这个值会快速地叠加上去。
            3、一旦连接建立起来了,客户端就会通过新建立的TCP管道来发送HTTP请求。数据到达时,Web服务器从TCP连接中读取请求报文,并对请求进行处理。因特网传输请求报文,以及服务器处理请求报文都需要时间。
            4、Web服务器会回送HTTP响应,这也需要花费时间。
            这些TCP网络时延大小取决于硬件速度、网络和服务器的负载,请求和响应报文的尺寸,以及客户端和服务器之间的距离。TCP协议的技术复杂性也会对时延产生巨大的影响。

    2.2、常见的影响性能的原因

    1、立握TCP连接建手
    2、TCP慢启动拥塞控制
    3、数据聚集的Nagle算法
    4、用于捎带确认的TCP延迟确认算法
    5、TIME_WAIT时延和端口耗尽。

    2.3、立握TCP连接建手

            建立一条新的TCP连接时,甚至是在发送任意数据之前,TCP软件之间会交换一系列的IP分组,对连接的有关参数进行沟通(如下图)。如果连接只用来传送少量数据,这些交换过程就会严重降低HTTP的性能。
            TCP连接握手需要经过以下几个步骤:
            1、请求新的TCP连接时,客户端要向服务器发送一个小的TCP分组(40~60字节左右)。这个分组中设置了一个特殊的SYN标记,说明这是一个连接请求(如图中a)。
            2、如果服务器接受了连接,就会对一些连接参数进行计算,并向客户端回送一个TCP分组,这个分组的SYN和ACK标记都被置位,说明连接请求已被接收(如图中b)。
            3、最后,客户端向服务器回送一条确认信息,通知它连接已成建立(如图中c)。现代的TCP栈都允许客户端在这个确认分组中发送数据。
            HTTP程序员不会看到这些分组,都是由TCP/IP软件管理,对其是不可见的。HTTP程序员只能看到创建TCP连接时存在的时延。
            通常HTTP事务都不会交换太多数据。SYN/SYN+ACK握手会产生一个可测量的时延。TCP连接的ACK分组通常都足够大,可以承载整个HTTP请求报文,而且很多HTTP服务器响应报文都可以放入一个IP分组中去。
    因此,小的HTTP事务可能会在TCP建立上花费50%或更多的时间。

    2.4、延迟确认

            由于因特网自身无法确认可靠的分组传输,所以TCP实现了自己的确认机制来确保数据的成功传输。
            每个TCP段都有一个序列号和数据完整性校验和。每个段的接收者收到完好的段时,都会向发送者回送小的确认分组。如果发送者没有在指定的窗口时间内收到确认信息,发送者就认为分组已被破坏或损毁,并重发数据。
            由于确认报文很小,所以TCP允许在发往相同方向的输出数据分组中对其进行"捎带"。TCP将返回的确认信息与输出的数据分组结合在一起,可以更有效地利用网络。为了增加确认报文找到同向传输数据分组的可能性,很多TCP栈都实现了一种“延迟确认”算法。延迟确认算法合在一个特定的窗口时间(100~200毫秒)内将输出确认存放在缓存区中,以寻找能够捎带它的输出数据分组。如果在那个时间段内没有输出数据分组,就将确认信息放在单独的分组中传送。
            HTTP具有双峰特征的请求-应答行为降低了捎带信息的可能。当希望有相反方向回传分组的时候,偏偏没有那么多。通常,延迟确认算法会引入相当大的时延。根据不同的操作系统,可以调整或禁止延迟确认算法。
            在对TCP栈的任何参数进行修改之前,一定要对自己在做什么有清醒的认识。TCP中引入这些算法的目的是防止设计欠佳的应用程序对因特网造成破坏。对TCP配置进行的任意修改,都要绝对确保应用程序不会引发这些算法所要避免的问题。

    2.5、TCP慢启动

            TCP数据传输的性能还取决于TCP连接的使用期。TCP连接会随着时间进行自我“调谐”,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调谐被称为TCP慢启动(slow start),用于防止因特网的突然过载和拥塞。
            TCP慢启动限制了一个TCP端点在任意时刻可以传输的分组数。每成功接收一个分组,发送端就有了发送另外两个分组的权限。如果某个HTTP事务有大量数据要发送,是不能一次性将所有分组都发送出去的。必须发送一个分组,等待确认,然后可以发送两个分组,每个分组都必须被确认,这样就可以发送四个分组了,以此类推。这种方式被称为“打开拥塞窗口”。
            由于存在这种拥塞控制特性,所以新连接的传输速度会比已经交换过一定量数据的、“以调谐”连接慢一些。由于已调谐连接更快一些,所以HTTP中有一些可以重复用现存连接的工具。

    2.6、Nagle算法

            TCP有一个数据流接口,应用程序能通过它把任意尺寸的数据放入TCP栈中——即使一次只放一个字节也可以。但是,每个TCP段中都至少装载了40个字节的标记和首部,所以如果TCP发送了大量包含少量数据的分组,网络的性能就会严重下降。
            Nagle算法试图在发送一个分组之前,将大量TCP数据绑定在一起,以提高网络效率。Nagle算法鼓励发送全尺寸的段,只有当所有其他分组都被确认之后,Nagle算法才允许发送非全尺寸的分组。如果其他分组仍然在传输过程中,就将那部分数据缓存起来。只有当挂起分组被确认,或者缓存中累积了足够发送一个全尺寸分组的数据时,才会将缓存的数据发送出去。
            Nagle算法会引发几种HTTP性能问题,首先,小的HTTP可能无法填满一个分组,可能会因为等待永远不会到来的额外数据而产生延时。其次Nagle算法与延迟确认之间的交互存在问题,Nagle算法会阻止数据的发送,直到有确认分组抵达位置,但确认分组自身会被延迟确认算法延迟100~200毫秒。
            HTTP程序常常会在自己的栈中设置参数TCP_NODELAY,禁止使用Nagle算法,提高性能。如果要这样的做的话,一定要确保会向TCP写入大块数据,这样就不会产生一堆小分组了。

    3、HTTP连接的处理

    3.1、Connection首部

            HTTP允许在客户端和最终的源端服务器之间存在一串HTTP中间实体(代理、高速缓存等)。可以从客户端开始,逐跳地将HTTP报文经过这些中间设备,转发到源端服务器上去。
            在某些情况下,两个相邻的HTTP应用程序会为它们共享的链接应用一组选项。HTTP的Connection首部字段中有一个由逗号分隔的连接标签列表,这些标签为此连接指定了一些不会传播到其他连接中去的选项。比如:可以用Connection:close来说明发送完下一条报文之后必须关闭的连接。
            Connection首部可以承载3种不同类型的标签,因此有时会让人费解:
            HTTP首部字段名,列出了只与此连接有关的首部;
            任意标签值,用于描述此连接的非标准选项;
            值close,说明操作完成之后需要关闭这条持久连接。
            如果连接标签中包含了一个HTTP首部字段的名称,那么这个首部字段就包含了与一些连接有关的信息,不能将其转发出去。在将报文转发出去之前,必须删除Connection首部列出的所有首部字段。由于Connection首部可以防止无意中对本地首部的转发,因此将逐跳首部名放入Connection首部被称为“对首部的保护”。

            下图是Connection首部允许发送端指定与连接有关的选项。


            HTTP应用程序收到一条带有Connection首部的报文时,接收端会解析发送端请求的所有选项,并将其应用。然后将会在将此报文转发给吓一跳地址之前,删除Connection首部以及Connection中列出的所有首部。而且,可能还会有少量没有作为Connection首部值列出,但一定不能被代理转发的逐跳首部。其中包含Proxy-Authenticate、Proxy-Connection、Transfer-Encoding和Upgrade。

    3.2、串行事务处理时延

            如果只对连接进行简单的管理,TCP的性能时延可能会叠加起来。假设一个包含了3个嵌入图片的Web页面,浏览器需要发起4个HTTP事务来显示此页面:1个用于顶层的HTML页面,3个用于嵌入的图片。如果每个事务都需要一条新的连接,那么连接时延和慢启动时延就会叠加起来,如下图:

            除了串行加载引入的实际时延之外,加载一幅图片时,页面上其他地方都没有动静也会让人觉得速度很慢。用户更希望同时加载多幅图片。
            串行加载的另一个缺点是,有些浏览器在对象加载完毕之前无法获知对象的尺寸,而且它们可能需要尺寸信息来决定将对象放在屏幕的什么位置上,所以在加载了足够多的对象之前,无法在屏幕上显示任何内容。在这种情况下,可能浏览器串行装载对象的进度很正常,但用户面对的却是空白的屏幕,对装载的速度一无所知。
            可以提高HTTP连接的性能的四种方法(后面详细介绍):

    • 并行连接:通过多条TCP连接发起并发的HTTP请求。
    • 持久连接:重用TCP连接,以消除连接和关闭的时延。
    • 管道化连接:通过共享的TCP了解发起并发的HTTP请求。
    • 复合的连接:交替传送请求和响应报文(实验阶段)

    4、并行连接

            浏览器可以先完整地请求原始的HTML页面,然后请求第一个嵌入对象,然后请求第二个嵌入对象等,以这种简单的方式对每个嵌入对象串行处理。但这样处理效率非常低。
            如下图所示,HTTP允许客户端打开多条连接,并行地执行多个HTTP事务,并行加载了4幅嵌入式图片,每个事务都有自己的TCP连接。

    4.1、并行连接可能会提高页面的加载速度

            包含嵌入对象的组合页面如果能通过并行连接克服单条连接的空载时间和带宽限制,加载速度也会有所提高。时延可以重叠起来,而且如果单条连接没有充分利用客户端的因特网带宽,可以将未用的带宽分配来装载其他对象。
            下图显示了并行连接的时间线,比单条连接快很多。首先要装载的是封闭的HTML页面,然后并行处理其他的3个事务,每个事务都有自己的连接。图片中的装载是并行的,连接的时延也是重叠的。

    4.2、并行连接不一定更快

            并行连接的速度可能会更快,但不一定总是更快的。客户端的网络带宽不足时,大部分的时间可能都是用来传送数据的。在这种情况下,一个连接到速度较快服务器上的HTTP事务就会很容易地耗尽所有可用的Modem带宽。如果并行加载,每个对象可能会去竞争有限的带宽,每个对象都会以较慢的速度按比例加载,这样带来的性能提升就很小,甚至没有提升。
            另外,打开大量连接会消耗很多内存资源,从而引发自身的性能问题。复杂的Web页面可能会有数十或数百个内嵌对象。客户端可能可以打开数百个连接,但服务器通常要同时处理很多其他用户的请求,所以很少有Web服务器希望出现这样的情况。这会造成服务器性能的严重下降,对高负荷的代理来说也同样如此。
            实际上,浏览器使用并行连接时,会将并行连接的总数限制在一个较小的值。服务器可以随意关闭来自特定客户端的超量连接。

    4.3、并行连接可能让人感觉更快

            并行连接并不总是能是页面加载更快一些,但即使实际上它们并没有加快页面的传输速度,并行连接通常也会让用户觉得页面加载得更快了,因为多个组件对象同时出现在屏幕上时,用户能够看到加载的进展。如果整个屏幕上有很多动作在进行,即使实际上秒表显示整个页面的下载时间更长,人也会认为Web页面加载得更快一些。

    5、持久连接

            Web客户端经常会打开到同一个站点的连接。一个Web页面上的大部分内嵌图片通常都来自同一个Web站点,而且相当一部分指向对象的超链接通常都指向同一个站点。因此,初始化了对某服务器HTTP请求的应用程序很可能会在不久的将来对那台服务器发起更多的请求,这种性质被称为站点本地服务(site locality)
            HTP/1.1允许HTTP设备在事务处理结束之后将TCP连接保持在打开状态,以便为未来的HTTP请求重用现存的连接。在事务处理结束之后仍然保持在打开状态的TCP连接被称为持久连接。非持久连接会在每个事务结束之后关闭。持久连接会在不同事务之间保持打开状态,直到客户端或服务器决定将其关闭为止。
            重用已对目标服务器打开的空闲持久连接,就可以避开缓慢的链接建立阶段。而且已经打开的链接还可以避免慢启动的拥塞适应阶段,以便更快速地进行数据传输。

    5.1、持久以及并行连接

            并行连接可以提高复合页面的传输速度,但存在以下缺点:

    • 每个事务都会打开/关闭一条新的连接,会耗费时间和带宽。
    • 由于TCP慢启动特性的存在,每条新链接的性能都会有所降低。
    • 可打开的并行连接数量实际上是有限的。

            持久连接有一些比并行连接更好的地方。持久连接降低了时延和连接建立的开销,将连接保持在已调谐状态,而且减少了打开连接的潜在数量。但是,管理持久连接时要特别小心,不然就会积累出大量的空闲连接,耗费本地以及远程客户端和服务器的资源。
            持久连接与并行连接配合使用可能是最高效的方式。现在,很多Web应用程序都会打开少量的并行连接,其中的每一个都是持久连接。持久连接有两种类型:比较老的HTTP/1.0+"keep-alive"连接,以及现代的HTTP/1.1“persistent”连接。

    5.2HTTP/1.0+keep-alive连接

            很多HTTP/1.0浏览器和服务器都进行了扩展,以支持一种被称为keep-alive连接的早期实验型持久连接。这些早期的持久连接受到一些互操作性设计方面的困扰,后续在HTTP/1.1上得到修正,但仍有很多客户端和服务器仍在使用keep-alive连接。
            下图中将在串行连接上实现4个HTTP事务的时间与在一条持久连接上实现同样事务所需的时间线进行了比较,由于去除了进行连接和关闭连接的开销,所以时间线有所缩减。

     5.3、Keep-Alive操作

            keep-alive已经不再使用了,而且在HTTP/1.1中也没有对它的说明。但是浏览器和服务器之间对keep-alive握手的使用仍然相当广泛,因此,HTTP的实现者应该做好与之进行交互操作的准备。
            实现HTTP/1.0keep-alive连接的客户端可以通过包含Connection:Keep-Alive首部请求将一条连接保持在打开状态。如果服务器愿意为下一条请求将连接保存在打开状态,就在响应中包含相同的首部。如果响应中没有这个首部,则客户端认为服务器不支持keep-alive,会在发回响应报文之后关闭连接。

    5.4、Keep-Alive选项

            keep-alive首部只是请求将连接保持在活跃状态,发出keep-alive请求之后,客户端和服务器并不一定会同意进行keep-alive会话。它们可以在任意时刻关闭空闲的keep-alive连接,并可随意限制keep-alive连接所处理事务的数量。
            可以用keep-alive通用首部中指定的、由逗号分隔的选项来调节keep-alive行为。

    • 参数timeout是在keep-alive响应首部发送的,它估计了服务器希望将连接保持在活跃状态的时间。这不是一个承诺值。
    • 参数max是在keep-alive响应首部发送的,它估计了服务器还希望为多少个事务保持此连接的活跃状态。这不是一个承诺值。
    • keep-alive首部还可以支持任意未经过处理的属性,这些属性主要用于诊断和调试。语法为name[=value]

        keep-alive首部完全是可选的,但只有提供Conne:Keep-Alive时才能使用它。
        如:Connection:Keep-Alive
               Keep-Alive:max=5,timeout=120
        上述例子表示服务器最多会为另外5个事务保持连接的打开状态,或者将打开状态保持到连接空闲了2分钟之后。

    5.5、Keep-Alive连接的限制和规则

            在HTTP/1.0中,keep-alive并不是默认使用的。客户端必须发送一个Connection:Keep-Alive请求首部来激活keep-alive连接。
            Connection:Keep-Alive首部必须随所有希望保持持久连接的报文一起发送。如果客户端没有发送Connection:Keep-Alive首部,服务器就会在那条请求之后关闭连接。
            客户端探明响应中没有Connection:Keep-Alive响应首部,就可以知道服务器发出响应之后是否会关闭连接了。
            只有在无需检测到连接的关闭即可确定报文实体主体部分长度的情况下,才能将连接保持在打开状态——也就是说实体的主体部分必须有正确的Content-Length,有多部件媒体类型,或者用分块传输编码的方式进行了编码。在一条keep-alive信道中回送错误的Content-Length是很糟糕的事,这样的话,事务处理的另一端就无法精确地检测出一条报文的结束和另一条报文的开始了。
            代理和网关必须执行Connection首部的规则。代理和网关必须在将报文转发出去或将其高速缓存之前,删除在Connection首部中命名的所有首部字段以及Connection首部自身。
    不应该与无法确定是否支持Connection首部的代理服务器建立keep-alive连接,以防出现哑代理问题。在实际应用中不是总能做到这一点。
            从技术上来讲,应该忽略所有来自HTTP/1.0设备的Connection首部字段(包括Connection:Keep-Alive),因为它们可能是由比较老的代理服务器误转发的。但实际上,尽管可能会有在老代理上挂起的危险,有些客户端和服务器还是会违反这个规则。
            除非重复发送请求会产生其他一些副作用,否则如果在客户端收到完整的响应之前连接就关闭了,客户端就一定要做好重试请求的准备。

    5.6、Keep-Alive和哑代理

            Web客户端的Connection:Keep-Alive首部应该只会对这条离开客户端的TCP链路产生影响。这就是将其称作“连接”首部的原因。如果客户端正在与一台Web服务器对话,客户端可以发送一个Connection:Keep-Alive首部来告知服务器它希望保持连接的活跃状态。如果服务器支持keep-alive,就回送一个Connection:Keep-Alive首部,否则就不回送。

            1、Connection首部和盲中继

            问题出在代理商,尤其是那些不理解Connection首部,而且不知道在沿着转发链路将其发送出去之前,应该将首部删除的代理。很多老的和简单的代理都是盲中继(blind relay),它们只是将字节从一个连接转发到另一个连接中去,不对Connection首部进行特殊处理。
            假如一个Web客户端正通过一个作为盲中继使用的哑代理与Web服务器进行对话,如下图情形:


            (1)、在a中,Web客户端向代理发送了一条报文,其中包含了Connection:Keep-Alive首部,如果可能的话请求建立一条keep-alive连接。客户端等待响应,以确定对方是否认可它对keep-alive信道的请求。
            (2)、哑代理收到了这条HTTP请求,但它不理解Connection首部。代理不知道keep-alive是什么意思,因此只是沿着转发链路将报文一字不漏地发送给服务器。但Connection首部是个逐跳首部,只适用于单条传输链路,不应该沿着传输链路向下传输。
            (3)、在b中,经过中继的HTTP请求抵达了Web服务器。当Web服务器收到经过代理转发的Connection:Keep-Alive首部时,会误以为代理希望进行Keep-Alive对话。对Web服务器来说没什么问题,服务器统一进行keep-alive对话,并在c中回送了一个Connection:Keep-Alive响应首部。所以,此时Web服务器认为它在与代理进行keep-alive对话,会遵循keep-alive的规则。但代理却对keep-alive一无所知。
            (4)、在d中,哑代理将Web服务器的响应报文回送给客户端,并将来自Web服务器的Connection:Keep-Alive首部一起传送出去。客户端看到这个首部,就会认为代理同意进行keep-alive对话。所以此时客户端和服务器都认为它们进行keep-alive对话,但与他们进行对话的代理却对keep-alive一无所知。
            (5)、由于代理对keep-alive一无所知,所以会将收到的数据都回送给客户端,然后等待源端服务器关闭连接。但源端服务器会认为代理已经显式地请求它将连接保持在打开状态了,所以就不糊去关闭连接。这样代理就会挂在那里等待连接的关闭。
            (6)、客户端在d中收到了回送的响应报文时,会立即转向下一条请求,在keep-alive连接上向代理发送另一条请求。而代理并认为同一条连接上会有其他请求的到来,请求被忽略,浏览器就在这里转圈,不会有任何进展了。
            (7)、这种错误的通信方式会使浏览器一直处于挂起状态,直到客户端或服务器将连接超时,并将其关闭为止。

            2、代理和逐跳首部

            为了避免代理通信问题的发生,现代的代理都绝不能转发Connection首部和所有名字出现在Connection值中的首部。因此,如果一个代理收到一个Connection:Keep-Alive首部,是不应该转发Connection首部,或所有名为Keep-Alive的首部的。另外,还有几个不能作为Connection首部值列出,也不能被代理转发或作为缓存响应使用的首部。其中包括Proxy-Authenticate、Proxy-Connection、Transfer-Encoding和Upgrade。

    5.7、插入Proxy-Connection

            Netscape的浏览器及代理实现者们提出了一个对盲中继问题的变通做法,这种做法并不要求所有的Web应用程序支持高版本的HTTP。这种变通做法引入了一个名为Proxy-Connection的新首部,解决了在客户端后面紧跟着一个盲中继所带来的问题——但并没有解决所有其他情况下存在的问题。在显式配置了代理的情况下,现在浏览器都实现了Proxy-Connection,很多代理都能过理解它。
            问题是哑代理盲目地转发Connection:Keep-Alive之类的逐跳首部惹出了麻烦。逐跳首部只与一条特定的连接有关,不能被转发。当下游服务器误将转发来的首部作为来自代理自身的请求解释,用它来控制自己的连接时,就会引发问题。
            在网景的变通做法是,浏览器会向代理发送非标准的Proxy-Connection扩展首部,而不是Connection首部。如果代理是盲中继,它会将无意义的Proxy-Connection首部转发给Web服务器,服务器会忽略此首部,不会带来任何问题。但如果代理是个聪明的代理,就用一个Connection首部取代无意义的Proxy-Connection首部,然后将其发送给服务器,以收到预期的结果。

            下图中,a~d显示了盲中继是如何向Web服务器转发Proxy-Connection首部,而不带来任何问题的,Web服务器忽略了这个首部,这样的客户端和代理,或者代理和服务器之间就不会建立起keep-alive连接。e~h中那个聪明的代理知道Proxy-Connection首部是对keep-alive对话的请求,它会发送自己的Connection:Keep-Alive首部来建立keep-alive连接。


            在客户端和服务器之间只有一个代理时可以用这种方案来解决问题。但下图所示,如果在哑代理的任意一侧还有一个聪明的代理,这个问题就会再次露头了。


            网络中出现“不可见”代理的情况现在变得很常见,这些代理可以是防火墙、拦截缓存,或者是反向代理服务器的加速器。这些设备对浏览器是不可见的,所以浏览器不会向它们发送Proxy-Connection收不。透明的Web应用程序正确地实现持久连接是非常重要的。

    5.8、HTTP/1.1持久连接

            HTTP/1.1逐渐停止了对keep-alive连接的支持,用持久连接(persistent connection)的改进型设计取代了它。持久连接的目的与keep-alive了解的目的相同,但工作机制更优。
            与HTTP/1.0的keep-alive连接不同,HTTP/1.1持久连接在默认情况下是激活的。除非特别指明,否则HTTP/1.1假定所有连接都是持久的。要在事务处理结束之后将连接关闭,HTTP/1.1假定所有连接都是持久的。要在事务处理结束之后将连接关闭,HTTP/1.1应用程序必须向报文中显示地添加一个Connection:close首部。这是与以前的HTTP协议版本很重要的去呗,在以前的版本中,keep-alive连接要么是可选的,要么根本就不支持。
            HTTP/1.1客户端假定在收到响应后,除非响应中包含了Connection:close首部,不然HTTP/1.1连接就仍维持在打开状态。但是,客户端和服务器仍然可以随时关闭空闲的连接。不发送Sonnection:close并不意味着服务器承诺永远将连接保持在打开状态。

    5.9、持久连接的限制和规则

            在持久连接的使用中有以下限制和需要澄清的问题:

    • 发送了Connection:close请求首部只有,客户端就无法在那条连接上发送更多的请求了。
    • 如果客户端不想在连接上发送其他请求了,就应该在最后一条请求中发送一个Connection:close请求首部。
    • 只有当连接上所有的报文都有正确的、自定义报文长度时,也就是说,实体主体部分的长度都和相应的Content-Length一致,或者是用分块传输编码方式编码的,连接才能持久保持。
    • HTTP/1.1的代理必须能够分别管理与客户端和服务器的持久连接——每个持久连接都只适用于一跳传输。
    • HTTP/1.1的代理服务器不应该与HTTP/1.0客户端建立持久连接,除非它们了解客户端的处理能力。实际上,这一点是很难做到的,很多厂商都会违背了这一原则。
    • 尽管服务器不应该试图在传输报文的过程中关闭连接,而且在关闭连接之前至少应该响应一条请求,但不管Connection首部取了什么值,HTTP/1.1设备都可以在任意时刻关闭连接。
    • HTTP/1.1应用程序必须能够从异步的关闭中恢复出来。只要不存在可能会累积起来的副作用,客户端都应该重试这条请求。
    • 除非重复发起请求会产生副作用,否则如果在客户端收到整条响应之前连接关闭了,客户端就必须要重新发起请求。
    • 一个用户客户端对任何服务器或代理最多只能维护两条持久连接,以防服务器过载。代理可能需要更多到服务器的连接来支持并发用户的通信,所以如果有N个用户试图访问服务器的话,代理最多要维持2N条到任意服务器或父代理的连接。

    6、管道化连接

    HTTP/1.1允许在持久连接上可选地使用请求管道。这是在keep-alive连接上的进一步性能优化。在响应到达之前,可以将多条请求放入队列。当第一条请求通过网络流向地球另一端的服务器时,第二天和第三条请求也可以开始发送了。在高时延网络条件下,这样做可以降低网络的环回时间,提高性能。
    下图中,c显示了持久连接时怎么消除TCP连接时延,以及管道化请求时如何消除传输时延的。

    对管道化连接有几条限制:
            如果HTTP客户端无法确认连接时持久的,就不应该使用管道。
            必须按照与请求相同的顺序回送HTTP响应。HTTP报文中没有序列号标签,因此如果收到的响应失序了,就没有办法将其余请求匹配起来了。
            HTTP客户端必须做好连接会在任意时刻关闭的准备,还要准备好重发所有未完成的管道化请求。如果客户端打开了一条持久连接,并立即发出了10条请求,服务器可能在只处理了5条请求之后就关闭了,剩下的5条请求会失败,客户端必须能够应对这些过早关闭连接的情况,重新发出这些请求。
            HTTP客户端不应该用管道化的方式发送会产生副作用的请求(例如POST),总之,出错的时候,管道化方式会阻碍客户端了解服务器执行的是一系列管道化请求中的哪一些。由于无法安全地重试POST这样的非幂等请求,所以出错时,就存在某些方法永远不会被执行的风险。

    7、关闭连接

    7.1、任意解除连接

            所有HTTP客户端、服务器或代理都可以在任意时刻关闭一条TCP传输连接。通常会在一条报文结束时关闭连接,但出错的时候,也可能在首部行的中间,或其他奇怪的地方关闭连接。
            对管道化持久连接来说,这种情形是很常见的。HTTP应用程序可以在经过任意一段时间之后,关闭持久连接。但是服务器永远都无法确定在它关闭“空闲”连接的那一刻,在线路那一头的客户端有没有数据要发送。乳沟出现这种情况,客户端就会在写入半截请求报文时发现出现了连接错误。

    7.2、Content-Length及截尾操作

            每条HTTP响应都应该有精确的Content-Length首部,用以描述响应主体的尺寸。一些老的HTTP服务器会省略Contenr-Length首部,或者包含错误的长度指示,这样就要依赖服务器发出的连接关闭来说明数据的真实末尾。
    客户端或代理收到一条随连接关闭而结束的HTTP响应,且实际传输的实体长度与Content-Length并不匹配时,接收端就应该质疑长度的正确性。
            如果接收端是个缓存代理,接收端就不应该缓存这条响应。代理应该将有问题的报文原封不动地转发出去,而不应该视图去“校正”Content-Length,以维护语义的透明性。

    7.3、连接关闭容限、重试、以及幂等性

            即使在非错误情况下,连接也可以在任意时刻关闭。HTTP应用程序要做好正确处理非预期关闭的准备。如果在客户端执行事务的过程中,传输连接关闭了,那么,除非事务处理会带来一些副作用,否则客户端就应该重新打开连接,并重试一次。对管道化连接来说,这种情况更加严重一些。客户端可以将大量请求放入队列中排队,但源端服务器可以关闭连接,这样就会留下大量未处理的请求,需要重新调度。
            副作用是很重要的问题。如果在发送出一些请求数据之后,收到返回结果之前,连接关闭了,客户端就无法百分百地确定服务器端实际激活了多少事务。有些事务,比如GET一个静态的HTML页面,可以反复执行多次,也不会有什么变化。但如果是POST订单,就不能重复执行,不然会有多张订单的情况。
            如果一个事务,不管是执行一次还是多次,得到的结果都相同,这个事务就是幂等待的。例如GET、HEAD、PUT、DELETE、TRACE和OPTION方法。客户端不应该以管道化方式传送非幂等请求,如POST,否则传输连接的过早终止会造成一些不确定的后果。要发送一条非迷瞪请求就需要等待来自前一条请求的响应状态。
            尽管用户Agent代理可能会让操作员来选择是否对请求进行重试,但一定不能重试非幂等方法或序列。

    7.4、正常关闭连接

    TCP连接是双向的。TCP连接的每一端都有一个输入队列和一个输出队列,用于数据的读或写。放入一端输出队列中的数据最终会出现在另一端的输出队列中。


    1、完全关闭与半关闭
    应用程序可以关闭TCP输入和输出信道中的任意一个,或者将两者都关闭了。套接字调用close()会将TCP连接的输入和输出信道都关闭了。这被称作“完全关闭”,如下图a所示。还可以用套接字调用shutdown()单独关闭输入或输出信道。这被称为“半关闭”,如下图b所示。


    2、TCP关闭及重置错误
            简单的HTTP应用程序可以只使用完全关闭。但当应用程序开始与很多其他类型的HTTP客户端、服务器和代理进行对话且开始使用管道化持久连接时,使用半关闭来防止对等实体收到非预期的写入错误就变得很重要了。
    总之,关闭连接的输出信道总是安全的。连接另一端的对等实体会在从其缓冲区中读出所有数据之后收到一条通知,说明流结束了,这样它就知道你将连接关闭了。

            关闭连接的输入信道比较危险,除非你知道另一端不打算再发送其他数据了。如果另一端向你已关闭的输入信道发送数据,操作系统就会向另一端的机器回送一条TCP“连接被对端重置”的报文,如下图所示。大部分操作系统都会将这种情况作为很严重的错误来处理,删除对端还未读取的所有缓存数据。对管道化连接来说,是很糟糕的事情。


            比如你已经在一条持久连接上发送了10条管道式请求了,响应也已经收到了,正在操作系统的缓冲区中存着。现在,假设你发送了第11条请求,但服务器认为你使用这条连接的时间已经够长了,决定将其关闭。那么你的第11条请求就会被发送到一条已关闭的连接上去,并会向你回送一条重置信息。这个重置信息会清空你的输入缓冲区。当最终要去读取数据的时候,会得到一个连接被对端重置的错误,已缓存的未读响应数据都丢失了,尽管其中大部分都已经成功抵达你的机器了。
    3、正常关闭
            HTTP规范建议,当客户端或服务器突然要关闭一条连接时,应该“正常地关闭传输连接”,但它并没有说明应该如何去做。
            总之,实现正常关闭的应用程序首先应该关闭他们的输入信道,然后等待连接另一端的对等实体关闭它的输出信道。当两端都告诉对方它们不会再发送任何数据之后,连接就会被完全关闭,而不会有重置的危险。
            但无法确保对等实体会实现半关闭,或对其进行检查。因此,想要正常关闭连接的应用程序应该先半关闭其输出信道,然后周期性地检查其输入信道的状态。如果在一定的时间区间内对端都没有关闭输入信道,应用程序就可以强制去关闭连接,节省资源。




    展开全文
  • 举例说明 假设您有两个表,每个表只有一个列,表数据如下 A B - - 1 3 2 4 3 5 4 6 ... 内连接是A表的所有行交上B表的所有行得出的结果集 select * from a INNER JOIN b on a.a = b.b; se...

    举例说明

    • 假设您有两个表,每个表只有一个列,表数据如下
      A    B
      -    -
      1    3
      2    4
      3    5
      4    6
      

      注意,(1,2)是A表唯一的,(3,4)是公共的,并且(5,6)是B表独有的

      内连接

      内连接是A表的所有行交上B表的所有行得出的结果集

      select * from a INNER JOIN b on a.a = b.b;
      select a.*, b.*  from a,b where a.a = b.b;
      
      a | b
      --+--
      3 | 3
      4 | 4
      

      左外连接

      左外连接是A表的所有行匹配上B表得出的结果集

    select * from a LEFT OUTER JOIN b on a.a = b.b;
    select a.*, b.*  from a,b where a.a = b.b(+);
    
    a |  b
    --+-----
    1 | null
    2 | null
    3 |    3
    4 |    4
    

    右外连接

    右外连接是B表的所有行匹配上A表得出的结果集

    select * from a RIGHT OUTER JOIN b on a.a = b.b;
    select a.*, b.*  from a,b where a.a(+) = b.b;
    
    a    |  b
    -----+----
    3    |  3
    4    |  4
    null |  5
    null |  6
    

    全连接

    全连接是A表的所有行并上B表的所有行得出的结果集

    select * from a FULL OUTER JOIN b on a.a = b.b;
    
     a   |  b
    -----+-----
       1 | null
       2 | null
       3 |    3
       4 |    4
    null |    6
    null |    5
    

     

    展开全文
  • 用两个表(a_table、b_table),关联字段a_table.a_id和b_table.b_id来演示一下MySQL的内连接、外连接( 左(外)连接、右(外)连接、全(外)连接)。 MySQL版本:Server version: 5.6.31 MySQL Community Server ...
  • 要求:连接两个表 R ⋈ S (表中标黄的数据后面会说到) R表: A B C 0 b c a c b c d 5 S表: A C D E 3 2 b a c 5 0 d a b 0 a c 0 b 1 先看两个表头,发现A C是重复出现的 所以连接...
  • 在查询多个表时,我们经常会用“连接查询”。连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志。 什么是连接查询呢?  概念:根据两个表或多个表的列之间的关系,从这些表中查询数据...
  •  left join (左连接):返回包括左表中的所有记录和右表中连接字段相等的记录。  right join (右连接):返回包括右表中的所有记录和左表中连接字段相等的记录。  inner join (等值连接或者叫内连接):只...
  • 1、左连接的定义:是以左表为基础,根据ON后给出的两表的条件将两表连接起来。结果会将左表所有的查询信息列出,而右表只列出ON后条件与左表满足的部分。左连接全称为左外连接,是外连接的一种。 下边以A表和B表为...
  • 近期需要对实验室的ftp服务器密码进行重新设置,然后就很理所当然的接入同一局域网,发现在连接的时候,报错 出现身份验证错误 要求的函数不受支持,CredSSP 加密 Oracle 修正 一个小伙伴自己重装过系统他就可以无...
  • 如果你连接远程数据库(Linux系统)并且很慢(具体症状为第一次连接打开所有的表貌似不是很慢,正常的,但是隔几分钟后任意打开一张表就很慢,即时数据很少的表依然很慢),我们用命令找到配置文件(mysql5.7的) sudo vi /...
  • 电脑显示已连接网络但是无internet访问 自己电脑不知道出什么问题了,连接到无限网络但是无法访问,一开始以为是自己双系统的问题,然后自己在ubuntu那边是可以正常上网的。 下面是自己的解决方法 方法一: ...
  • MQTT控制报文(连接

    2018-08-17 16:23:47
    1.CONNECT – 连接服务端 1.1 可变报文 (协议名 + 协议级别 + 连接标志 + 保持连接) 1.1.1 协议名(内容固定,标识是MQTT协议 。 前2个字节表示长度,后4个字节ASCII码的MQTT) 1.1.2 协议级别(8位的无符号...
  • 问题:远程连接公司的teamviewer时,一直无法连接,且报原因未知。 分析:电脑是联网状态,本机和远程机的teamviewer也重启过几次,密码也是正确的,还是不行。 解决方案:网上查了一下,可能是网络的问题,电脑的...
  • 用FileZilla连接服务器时,显示错误:错误:20秒后无活动,连接超时 错误:无法连接到服务器 解决方法: 检查基本的内容 主机是否写错 端口是否自定义,默认21 检查用户名和密码是否错误 如果连接的是外部服务器 ...
  • 前不久有俩个盆友和我探讨这些问题,我做了个简单的总结分享给打架,明天就是国庆了祝大家玩的开心,主要分享设计数据库连接池原理以及要处理关键点,本文只挑选某一种实现方式来简单阐述,暂不涉及事务相关。...
  • 在使用数据库查询语句时,单表的查询有时候不能满足项目的业务需求,在项目开发过程中,有很多需求都是要涉及到多表的连接查询,总结一下mysql中的多表关联查询 一,内连接查询 是指所有查询出的结果都是能够在连接...
  • 计算机如何建立远程桌面连接有的时候身在远方,想查看或者调用自己狗窝(宿舍或者家)里的机器的文件,怎么办呢?可以通过远程桌面登录自己个的电脑,利用剪切板的功能便可以实现文件之间的传送。当然,假如家里的...
  • 什么是连接池 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。 为什么要使用连接池  数据库连接是一种关键的有限的昂贵的资源,这一点在多...
1 2 3 4 5 ... 20
收藏数 5,016,942
精华内容 2,006,776
关键字:

连接