精华内容
下载资源
问答
  • SSDP 简单服务发现协议

    千次阅读 2017-02-06 14:11:54
    标签: cachenetwork网络algorithmextservice ...SSDP 简单服务发现协议,是应用层协议,是构成UPnP(通用即插即用)技术的核心协议之一。它为网络客户端(network client)提供了一种发现网络服务(network s
     
    
    标签: cachenetwork网络algorithmextservice
    2011-07-26 15:33 31146人阅读 评论(2) 收藏 举报

    版权声明:本文为博主原创文章,未经博主允许不得转载。

    SSDP 简单服务发现协议,是应用层协议,是构成UPnP(通用即插即用)技术的核心协议之一。它为网络客户端(network client)提供了一种发现网络服务(network services)的机制,采用基于通知和发现路由的多播方式实现。

    SSDP多播地址:239.255.255.250:1900(IPv4),FF0x::C(IPv6)

    两种类型的SSDP请求消息会通过SSDP多播地址发送:

    1. 发现请求(Discovery request 或查询请求)。SSDP客户端向此地址发送HTTP UDP 发现请求,查询某种类型的服务。SSDP服务在此地址上监听服务发现请求。当服务监听到的HTTP UDP 发现请求和它自己提供的服务匹配时,它以单播方式发送HTTP UDP 响应。

    2. 存在通知(notification)。SSDP服务向此多播地址发送HTTP UDP 通知消息来宣布自己的存在。

     

    发现结果(discovery results)和存在通知消息(presence announcements)提供的信息包括:

    服务的类型URI

    服务名称USN:唯一标识一种服务实例。

    位置信息:发现结果和存在通知可包含一个或多个位置URI,客户端利用位置信息可以找到它需要的服务。

    期限信息:客户端在自己的cache中保存此服务多长时间。如果期限过了,关于此服务的信息会被从cache中拿掉。当客户端接收到的发现结果或存在通知包含的USN和cache中的某条匹配,则更新。

    客户端的服务缓存像下面这样:

    【SSDP发现请求】ssdp:discover

    ssdp:discover 必须包含一个ST头,客户端使用ST头来表明他们想发现的服务类型。ssdp:discover 必须包含一个带 *  的请求URI。

    M-SEARCH * HTTP/1.1

    S: uuid:ijklmnop-7dec-11d0-a765-00a0c91e6bf6

    Host: 239.255.255.250:1900

    Man: "ssdp:discover"

    ST: ge:fridge

    MX: 3

    各HTTP协议头的含义:

    HOST:设置为协议保留多播地址和端口,必须是:239.255.255.250:1900(IPv4)或FF0x::C(IPv6)

    MAN:设置协议查询的类型,必须是:ssdp:discover

    MX:设置设备响应最长等待时间。设备响应在0和这个值之间随机选择响应延迟的值,这样可以为控制点响应平衡网络负载。

    ST:设置服务查询的目标,它必须是下面的类型:

    -ssdp:all 搜索所有设备和服务

    -upnp:rootdevice 仅搜索网络中的根设备

    -uuid:device-UUID 查询UUID标识的设备

    -urn:schemas-upnp-org:device:device-Type:version 查询device-Type字段指定的设备类型,设备类型和版本由UPNP组织定义。

    -urn:schemas-upnp-org:service:service-Type:version 查询service-Type字段指定的服务类型,服务类型和版本由UPNP组织定义。

     

    SSDP服务发现自己的服务类型和ST中指明的服务类型匹配时,可以向ssdp:discover来自的IP地址/端口响应。响应消息应该包含服务的位置信息(Location 或AL头),ST和USN头。响应消息应该包含cache控制信息(max-age 或者 Expires头),如果两者都包含了,Expires 头优先,如果两者都缺失,那么这条服务消息不能被cache。

    HTTP/1.1 200 OK

    S: uuid:ijklmnop-7dec-11d0-a765-00a0c91e6bf6

    Ext:

    Cache-Control: no-cache="Ext", max-age = 5000

    ST: ge:fridge

    USN: uuid:abcdefgh-7dec-11d0-a765-00a0c91e6bf6

    AL: <blender:ixl><http://foo/bar>

    各HTTP协议头的含义简介:

    CACHE-CONTROL:max-age指定通知消息存活时间,如果超过此时间间隔,控制点可以认为设备不存在

    DATE:指定响应生成的时间

    EXT:向控制点确认MAN头域已经被设备理解

    LOCATION:包含根设备描述得URL地址

    SERVER:饱含操作系统名,版本,产品名和产品版本信息

    ST:内容和意义与查询请求的相应字段相同

    USN:表示不同服务的统一服务名,它提供了一种标识出相同类型服务的能力。

     

    【SSDP存在通知消息】

    SSDP服务通过存在通知消息来向客户端宣布自己的存在,更新期限信息,更新位置信息。

    ssdp:alive 消息必须将 NT 设置成自己的服务类型,USN头设置成自己的USN。ssdp:alive 应该包括Location或者AL头,如果没有DNS支持的话,使用SSDP服务的IP地址来代表位置。ssdp:alive还应该包括cache控制信息,max-age或者Expires头。

    NOTIFY * HTTP/1.1

    Host: 239.255.255.250:reservedSSDPport

    NT: blenderassociation:blender

    NTS: ssdp:alive

    USN: someunique:idscheme3

    AL: <blender:ixl><http://foo/bar>

    Cache-Control: max-age = 7393

    ssdp:alive 没有响应消息。

     

    SSDP服务可以发送ssdp:byebye 来宣布自己下线。ssdp:byebye 必须将NT设置成自己的服务类型,将USN头设置成自己的USN。ssdp:byebye 也没有响应消息。当客户端接收到ssdp:byebye 消息,删掉cache里面的相关条目。

    NOTIFY * HTTP/1.1

    Host: 239.255.255.250:reservedSSDPport

    NT: someunique:idscheme3

    NTS: ssdp:byebye

    USN: someunique:idscheme3

     

    【SSDP Auto-Shut-Off Algorithm】

    A mechanism is needed to ensure that SSDP does not cause such a high level of traffic that it overwhelms the network it is running on.

    【ssdp:all】

    A mechanism is needed to enable a client to enumerate all the services available on a particular SSDP multicast channel/port.

     

    【参考】

    SSDP 协议原文:http://tools.ietf.org/html/draft-cai-ssdp-v1-03

    http://www.cnblogs.com/debin/archive/2009/12/01/1614543.html

    展开全文
  • 简单服务发现协议SSDP

    千次阅读 2014-04-16 14:23:06
    SSDP:Simple Sever Discovery Protocol,简单服务发现协议,此协议为网络客户提供一种无需任何配置、管理和维护网络设备服务的机制。此协议采用基于通知和发现路由的多播发现方式实现。协议客户端在保留的多播地址:...

    SSDP:Simple Sever Discovery Protocol,简单服务发现协议是一种应用层协议(常用于寻找upnp设备),此协议为网络客户提供一种无需任何配置、管理和维护网络设备服务的机制。此协议采用基于通知和发现路由的多播发现方式实现。协议客户端在保留的多播地址:239.255.255.250:1900(IPV4)发现服务,(IPv6 是:FF0x::C)同时每个设备服务也在此地址上上监听服务发现请求。如果服务监听到的发现请求与此服务相匹配,此服务会使用单播方式响应。

    常见的协议请求消息有两种类型,第一种是服务通知,设备和服务使用此类通知消息声明自己存在;第二种是查询请求,协议客户端用此请求查询某种类型的设备和服务。请求消息中包含设备的特定信息或者某项服务的信息,例如设备类型、标识符和指向设备描述文档的URL地址。下图显示这两类通知消息和HTTP协议的关系:

    设备发现过程允许控制点使用一个设备类型或标识,或者是服务类型进行查询。这要求标准设备或服务类型,或者设备特定实例的发现和广告消息基于一个独一无二的标识,UPnP设备和服务类型的定义是UPnP论坛工作委员会的责任。从设备获得响应的内容基本上与多址传送的设备广播相同,只是采用单址传送方式。

    SSDP 协议消息

    1、设备查询消息

      当一个控制点加入到网络中时,设备发现过程允许控制点寻找网络上感兴趣的设备。发现消息包括设备的一些特定信息或者某项服务的信息,例如它的类型、标识符、和指向XML设备描述文档的指针。从设备获得响应从本质上说,内容与多址传送的设备广播相同,只是采用单址传送方式。设备查询通过HTTP协议扩展M-SEARCH方法实现的。典型的设备查询请求消息格式:

    M-SEARCH * HTTP/1.1
    HOST: 239.255.255.250:1900
    MAN: "ssdp:discover"
    MX: seconds to delay response
    ST: search target

    各HTTP协议头的含义简介:

    HOST:设置为协议保留多播地址和端口,必须是:239.255.255.250:1900(IPv4)或FF0x::C(IPv6)

    MAN:设置协议查询的类型,必须是:ssdp:discover

    MX:设置设备响应最长等待时间,设备响应在0和这个值之间随机选择响应延迟的值。这样可以为控制点响应平衡网络负载。

    ST:设置服务查询的目标,它必须是下面的类型:

    ssdp:all 搜索所有设备和服务 
    upnp:rootdevice 仅搜索网络中的根设备 
    uuid:device-UUID 查询UUID标识的设备 
    urn:schemas-upnp-org:device:device-Type:version 查询device-Type字段指定的设备类型,设备类型和版本由UPNP组织定义。 
    urn:schemas-upnp-org:service:service-Type:version 查询service-Type字段指定的服务类型,服务类型和版本由UPNP组织定义。

    在设备接收到查询请求并且查询类型(ST字段值)与此设备匹配时,设备必须向多播地址239.255.255.250:1900回应响应消息。典型:

    HTTP/1.1 200 OK
    CACHE-CONTROL: max-age = seconds until advertisement expires
    DATE: when reponse was generated
    EXT:
    LOCATION: URL for UPnP description for root device
    SERVER: OS/Version UPNP/1.0 product/version
    ST: search target
    USN: advertisement UUID

    各HTTP协议头的含义简介:

    CACHE-CONTROLmax-age指定通知消息存活时间,如果超过此时间间隔,控制点可以认为设备不存在
    DATE指定响应生成的时间
    EXT向控制点确认MAN头域已经被设备理解
    LOCATION包含根设备描述得URL地址
    SERVER饱含操作系统名,版本,产品名和产品版本信息
    ST内容和意义与查询请求的相应字段相同
    USN表示不同服务的统一服务名,它提供了一种标识出相同类型服务的能力。


    2、设备通知消息

    在设备加入网络,UPnP发现协议允许设备向控制点广告它的服务。它使用向一个标准地址和端口多址传送发现消息来实现。控制点在此端口上侦听是否有新服务加入系统。为了通知所有设备,一个设备为每个其上的嵌入设备和服务发送一系列相应的发现消息。每个消息也包含它表征设备或服务的特定信息。

    3.1.1 ssdp:alive消息

    在设备加入系统时,它采用多播传送方式发送发现消息,包括告知设备包含的根设备信息,所有嵌入设备以及它包含的服务。每个发现消息包含四个主要对象:

    1. 在NT头中包含的潜在搜索目标。
    2. 在USN头中包含的复合发现标识
    3. 在LOCATION头中关于设备信息的URL地址
    4. 在CACHE-CONTROL头中表示的广告消息的合法存在时间。

    对于根设备,存在三种发现消息:

    NTUSN
    根设备的UUID根设备的UUID
    设备类型:设备版本根设备的UUID,设备类型:设备版本
    upnp:rootdevice根设备的UUID,设备类型和upnp:rootdevice

    对于嵌入式设备,存在两种发现消息:

    NTUSN
    嵌入设备的UUID嵌入设备的UUID
    设备类型:设备版本嵌入设备的UUID,设备类型和设备版本

    对于每个服务:

    NTUSN
    服务类型:服务版本相关设备的UUID,服务类型和服务版本

    由于UDP协议是不可信的,设备应该发送多次设备发现消息。而且为了降低控制点无法收到设备或服务广告消息的可能性,设备应该定期发送它的广告消息。在设备加入网络时,它必须用NOTIFY方法发送一个多播传送请求。NOTIFY方法发送的请求没有回应消息,典型的设备通知消息格式如下:

    NOTIFY * HTTP/1.1
    HOST: 239.255.255.250:1900CACHE-CONTROL: max-age = seconds until advertisement expires
    LOCATION: URL for UPnP description for root device
    NT: search target
    NTS: ssdp:alive
    USN: advertisement UUID

    各HTTP协议头的含义简介:

    HOST设置为协议保留多播地址和端口,必须是239.255.255.250:1900。
    CACHE-CONTROLmax-age指定通知消息存活时间,如果超过此时间间隔,控制点可以认为设备不存在
    LOCATION包含根设备描述得URL地址
    NT在此消息中,NT头必须为服务的服务类型。
    NTS表示通知消息的子类型,必须为ssdp:alive
    USN表示不同服务的统一服务名,它提供了一种标识出相同类型服务的能力。

    一个发现响应可以包含0个、1个或者多个服务类型实例。为了做出分辨,每个服务发现响应包括一个USN:根设备的标识。在同样的设备里,一个服务类型的多个实例必须用包含USN:ID的服务标识符标识出来。例如,一个灯和电源共用一个开关设备,对于开关服务的查询可能无法分辨出这是用于灯的。UPNP论坛工作组通过定义适当的设备层次以及设备和服务的类型标识分辨出服务的应用程序场景。这么做的缺点是需要依赖设备的描述URL。

    3.1.2 ssdp:byebye消息

    在设备和它的服务将要从网络中卸载时,设备应该对于每个未超期的ssdp:alive消息多播方式传送ssdp:byebye消息。但如果设备突然从网络卸载,它可能来不及发出这个通知消息。因此,发现消息必须在CACHE-CONTROL包含超时值,如果不重新发出广告消息,发现消息最后超时并从控制点的缓存中除去。典型的设备卸载消息格式如下:

    NOTIFY * HTTP/1.1
    HOST: 239.255.255.250:1900NT: search target
    NTS: ssdp:byebye
    USN: advertisement UUID各HTTP协议头的含义简介:
    HOST	设置为协议保留多播地址和端口,必须是239.255.255.250:1900
    NT	在此消息中,NT头必须为服务的服务类型。
    NTS	表示通知消息的子类型,必须为ssdp:alive
    USN	表示不同服务的统一服务名,它提供了一种标识出相同类型服务的能力

    专有设备或服务可以不遵循标准的UPNP模版。但如果设备或服务提供UPNP发现、描述、控制和事件过程的所有对象,它的行为就像一个标准的UPNP设备或服务。为了避免命名冲突,使用专有设备命名时除了UPNP域之外必须包含一个前缀"urn:schemas-upnp-org"。在与标准模版相同时,应该使用整数版本号。但如果与标准模版不同,不可以使用设备复用和徽标。

    简单设备发现协议不提供高级的查询功能,也就是说,不能完成某个具有某种服务的设备这样的复合查询。在完成设备或者服务发现之后,控制点可以通过设备或服务描述的URL地址完成更为精确的信息查询。


    展开全文
  • 简单服务发现协议SSDP【转】

    千次阅读 2018-08-20 14:08:47
    SSDP:Simple Sever Discovery Protocol,简单服务发现协议是一种应用层协议(常用于寻找upnp设备),此协议为网络客户提供一种无需任何配置、管理和维护网络设备服务的机制。此协议采用基于通知和发现路由的多播发现...

    来自:https://blog.csdn.net/wuruixn/article/details/23843877

    SSDP:Simple Sever Discovery Protocol,简单服务发现协议是一种应用层协议(常用于寻找upnp设备),此协议为网络客户提供一种无需任何配置、管理和维护网络设备服务的机制。此协议采用基于通知和发现路由的多播发现方式实现。协议客户端在保留的多播地址:239.255.255.250:1900(IPV4)发现服务,(IPv6 是:FF0x::C)同时每个设备服务也在此地址上上监听服务发现请求。如果服务监听到的发现请求与此服务相匹配,此服务会使用单播方式响应。

    常见的协议请求消息有两种类型,第一种是服务通知,设备和服务使用此类通知消息声明自己存在;第二种是查询请求,协议客户端用此请求查询某种类型的设备和服务。请求消息中包含设备的特定信息或者某项服务的信息,例如设备类型、标识符和指向设备描述文档的URL地址。下图显示这两类通知消息和HTTP协议的关系:

     

    设备发现过程允许控制点使用一个设备类型或标识,或者是服务类型进行查询。这要求标准设备或服务类型,或者设备特定实例的发现和广告消息基于一个独一无二的标识,UPnP设备和服务类型的定义是UPnP论坛工作委员会的责任。从设备获得响应的内容基本上与多址传送的设备广播相同,只是采用单址传送方式。

    SSDP 协议消息

    1、设备查询消息

      当一个控制点加入到网络中时,设备发现过程允许控制点寻找网络上感兴趣的设备。发现消息包括设备的一些特定信息或者某项服务的信息,例如它的类型、标识符、和指向XML设备描述文档的指针。从设备获得响应从本质上说,内容与多址传送的设备广播相同,只是采用单址传送方式。设备查询通过HTTP协议扩展M-SEARCH方法实现的。典型的设备查询请求消息格式:

    M-SEARCH * HTTP/1.1
    HOST: 239.255.255.250:1900
    MAN: "ssdp:discover"
    MX: seconds to delay response
    ST: search target

    各HTTP协议头的含义简介:

    HOST:设置为协议保留多播地址和端口,必须是:239.255.255.250:1900(IPv4)或FF0x::C(IPv6)

    MAN:设置协议查询的类型,必须是:ssdp:discover

    MX:设置设备响应最长等待时间,设备响应在0和这个值之间随机选择响应延迟的值。这样可以为控制点响应平衡网络负载。

    ST:设置服务查询的目标,它必须是下面的类型:

    ssdp:all 搜索所有设备和服务 
    upnp:rootdevice 仅搜索网络中的根设备 
    uuid:device-UUID 查询UUID标识的设备 
    urn:schemas-upnp-org:device:device-Type:version 查询device-Type字段指定的设备类型,设备类型和版本由UPNP组织定义。 
    urn:schemas-upnp-org:service:service-Type:version 查询service-Type字段指定的服务类型,服务类型和版本由UPNP组织定义。

    在设备接收到查询请求并且查询类型(ST字段值)与此设备匹配时,设备必须向多播地址239.255.255.250:1900回应响应消息。典型:

    HTTP/1.1 200 OK
    CACHE-CONTROL: max-age = seconds until advertisement expires
    DATE: when reponse was generated
    EXT:
    LOCATION: URL for UPnP description for root device
    SERVER: OS/Version UPNP/1.0 product/version
    ST: search target
    USN: advertisement UUID

    各HTTP协议头的含义简介:

    CACHE-CONTROLmax-age指定通知消息存活时间,如果超过此时间间隔,控制点可以认为设备不存在
    DATE指定响应生成的时间
    EXT向控制点确认MAN头域已经被设备理解
    LOCATION包含根设备描述得URL地址
    SERVER饱含操作系统名,版本,产品名和产品版本信息
    ST内容和意义与查询请求的相应字段相同
    USN表示不同服务的统一服务名,它提供了一种标识出相同类型服务的能力。

     

    2、设备通知消息

    在设备加入网络,UPnP发现协议允许设备向控制点广告它的服务。它使用向一个标准地址和端口多址传送发现消息来实现。控制点在此端口上侦听是否有新服务加入系统。为了通知所有设备,一个设备为每个其上的嵌入设备和服务发送一系列相应的发现消息。每个消息也包含它表征设备或服务的特定信息。

    3.1.1 ssdp:alive消息

    在设备加入系统时,它采用多播传送方式发送发现消息,包括告知设备包含的根设备信息,所有嵌入设备以及它包含的服务。每个发现消息包含四个主要对象:

    1. 在NT头中包含的潜在搜索目标。
    2. 在USN头中包含的复合发现标识
    3. 在LOCATION头中关于设备信息的URL地址
    4. 在CACHE-CONTROL头中表示的广告消息的合法存在时间。

    对于根设备,存在三种发现消息:

    NTUSN
    根设备的UUID根设备的UUID
    设备类型:设备版本根设备的UUID,设备类型:设备版本
    upnp:rootdevice根设备的UUID,设备类型和upnp:rootdevice

    对于嵌入式设备,存在两种发现消息:

    NTUSN
    嵌入设备的UUID嵌入设备的UUID
    设备类型:设备版本嵌入设备的UUID,设备类型和设备版本

    对于每个服务:

    NTUSN
    服务类型:服务版本相关设备的UUID,服务类型和服务版本

     

    由于UDP协议是不可信的,设备应该发送多次设备发现消息。而且为了降低控制点无法收到设备或服务广告消息的可能性,设备应该定期发送它的广告消息。在设备加入网络时,它必须用NOTIFY方法发送一个多播传送请求。NOTIFY方法发送的请求没有回应消息,典型的设备通知消息格式如下:

    NOTIFY * HTTP/1.1
    HOST: 239.255.255.250:1900CACHE-CONTROL: max-age = seconds until advertisement expires
    LOCATION: URL for UPnP description for root device
    NT: search target
    NTS: ssdp:alive
    USN: advertisement UUID

    各HTTP协议头的含义简介:

    HOST设置为协议保留多播地址和端口,必须是239.255.255.250:1900。
    CACHE-CONTROLmax-age指定通知消息存活时间,如果超过此时间间隔,控制点可以认为设备不存在
    LOCATION包含根设备描述得URL地址
    NT在此消息中,NT头必须为服务的服务类型。
    NTS表示通知消息的子类型,必须为ssdp:alive
    USN表示不同服务的统一服务名,它提供了一种标识出相同类型服务的能力。

    一个发现响应可以包含0个、1个或者多个服务类型实例。为了做出分辨,每个服务发现响应包括一个USN:根设备的标识。在同样的设备里,一个服务类型的多个实例必须用包含USN:ID的服务标识符标识出来。例如,一个灯和电源共用一个开关设备,对于开关服务的查询可能无法分辨出这是用于灯的。UPNP论坛工作组通过定义适当的设备层次以及设备和服务的类型标识分辨出服务的应用程序场景。这么做的缺点是需要依赖设备的描述URL。

    3.1.2 ssdp:byebye消息

    在设备和它的服务将要从网络中卸载时,设备应该对于每个未超期的ssdp:alive消息多播方式传送ssdp:byebye消息。但如果设备突然从网络卸载,它可能来不及发出这个通知消息。因此,发现消息必须在CACHE-CONTROL包含超时值,如果不重新发出广告消息,发现消息最后超时并从控制点的缓存中除去。典型的设备卸载消息格式如下:

    NOTIFY * HTTP/1.1
    HOST: 239.255.255.250:1900NT: search target
    NTS: ssdp:byebye
    USN: advertisement UUID各HTTP协议头的含义简介:
    HOST	设置为协议保留多播地址和端口,必须是239.255.255.250:1900
    NT	在此消息中,NT头必须为服务的服务类型。
    NTS	表示通知消息的子类型,必须为ssdp:alive
    USN	表示不同服务的统一服务名,它提供了一种标识出相同类型服务的能力

    专有设备或服务可以不遵循标准的UPNP模版。但如果设备或服务提供UPNP发现、描述、控制和事件过程的所有对象,它的行为就像一个标准的UPNP设备或服务。为了避免命名冲突,使用专有设备命名时除了UPNP域之外必须包含一个前缀"urn:schemas-upnp-org"。在与标准模版相同时,应该使用整数版本号。但如果与标准模版不同,不可以使用设备复用和徽标。

    简单设备发现协议不提供高级的查询功能,也就是说,不能完成某个具有某种服务的设备这样的复合查询。在完成设备或者服务发现之后,控制点可以通过设备或服务描述的URL地址完成更为精确的信息查询。

    展开全文
  • c++简单实现http协议服务器和客户端

    千次阅读 2020-03-01 17:08:00
    C++ 简单实现HTTP GET/POST 请求 ...文章将简单介绍HTTP协议,同时以C++方式分别实现HTTP GET、POST 请求 HTTP 请求报文 HTTP请求报文的一般格式由4部分组成:请求行、请求头部、空行、请求数据。如...
    C++ 简单实现HTTP GET/POST 请求
    

    HTTP(超文本传输协议)是一种客户端与服务端的传输协议,最早用于浏览器和服务器之间的通信,后来因为其使用灵活、方便等特点,广泛用于客户端与服务端的通信。文章将简单介绍HTTP协议,同时以C++方式分别实现HTTP GET、POST 请求

    HTTP 请求报文

    HTTP请求报文的一般格式由4部分组成:请求行、请求头部、空行、请求数据。如下图所示:

     

    1.jpg

    请求行:包含3部分内容:请求方法,URL,协议版本。形式如:GET /?aaa=1 HTTP/1.1。请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS等。URL指请求服务端的地址,可以是相对地址或域名形式的绝对地址。协议版本主要有HTTP/1.1 HTTP/1.0 HTTP/0.9,后面两种已很少使用了。

    请求头部:以key/value形式成对表示头部参数,以英文冒号分隔。key名称的约定写法为Key,Key-Name,自定义key名称一般以“X-”开头。如php的声明“X-Powered-By:PHP/5.5.4-1”

    空行:用来标识请求头部的数据已结束。

    请求数据:可选项,这块内容只在POST方式下使用,作为POST的数据表示区域。使用这块内容,要在请求头部以Content-Length声明请求数据长度,以Content-Type声明请求数据类型。

    HTTP POST请求

    HTTP POST方式是把请求参数放到HTTP请求报文的请求数据中,为了让例子更容易看懂,仅保留HTTP Post关键参数,你还可以自定义一些参数,比如浏览器喜欢用的User-Agent,Accept,Connection等等

     

    char *pHttpPost = "POST %s HTTP/1.1\r\n"
        "Host: %s:%d\r\n"
        "Content-Type: application/x-www-form-urlencoded\r\n"
        "Content-Length: %d\r\n\r\n"
        "%s";
     
    char* addr = "http://localhost/post.php";
    char* host = "127.0.0.1";
    int port = 80;
    char* msg = "aaa=1&bbb=2";
     
    char strHttpPost[1024] = {0};
    sprintf(strHttpPost, pHttpPost, addr, host, port, strlen(msg), msg);
     
    //这里忽略掉了socket连接代码
     
    send(sockClient, strHttpPost, strlen(strHttpPost), 0);
    

    HTTP GET请求

    HTTP GET方式是把请求参数放到HTTP请求报文的请求行URL中,所以请求行就是“GET /?aaa=1&bbb=2 HTTP/1.1\r\n”。URL最大长度通常浏览器取255,这和文件路径最大长度有关。虽然HTTP允许更大长度,但不建议怎么做,如果太长了,可以考虑换成POST方式

     

    char *pHttpGet = "GET %s?%s HTTP/1.1\r\n"
        "Host: %s:%d\r\n\r\n";
     
    char* addr = "http://localhost/get.php";
    char* host = "127.0.0.1";
    int post = 80;
    char* msg = "aaa=1&bbb=2";
     
    char strHttpGet[1024] = {0};
    sprintf(strHttpGet, pHttpGet, addr, msg,  host, post);
     
    //这里忽略掉了socket连接代码
     
    send(sockClient, strHttpGet, strlen(strHttpGet), 0);
    

    实现的HTTP

     

    #include "HttpConnect.h"
     
    #ifdef WIN32
    #pragma comment(lib,"ws2_32.lib")
    #endif
    HttpConnect::HttpConnect()
    {
    #ifdef WIN32
        //此处一定要初始化一下,否则gethostbyname返回一直为空
        WSADATA wsa = { 0 };
        WSAStartup(MAKEWORD(2, 2), &wsa);
    #endif
    }
    HttpConnect::~HttpConnect()
    {
    }
    void HttpConnect::socketHttp(std::string host, std::string request)
    {
        int sockfd;
        struct sockaddr_in address;
        struct hostent *server;
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        address.sin_family = AF_INET;
        address.sin_port = htons(80);
        server = gethostbyname(host.c_str());
        memcpy((char *)&address.sin_addr.s_addr,(char*)server->h_addr, server->h_length);
        if(-1 == connect(sockfd,(struct sockaddr *)&address,sizeof(address))){
            DBG <<"connection error!"<<std::endl;
            return;
        }
        DBG << request << std::endl;
    #ifdef WIN32
        send(sockfd, request.c_str(),request.size(),0);
    #else
        write(sockfd,request.c_str(),request.size());
    #endif
        char buf[1024*1024] = {0};
        int offset = 0;
        int rc;
    #ifdef WIN32
        while(rc = recv(sockfd, buf+offset, 1024,0))
    #else
        while(rc = read(sockfd, buf+offset, 1024))
    #endif
        {
            offset += rc;
        }
    #ifdef WIN32
        closesocket(sockfd);
    #else
        close(sockfd);
    #endif
        buf[offset] = 0;
        DBG << buf << std::endl;
    }
    void HttpConnect::postData(std::string host, std::string path, std::string post_content)
    {
        //POST请求方式
        std::stringstream stream;
        stream << "POST " << path;
        stream << " HTTP/1.0\r\n";
        stream << "Host: "<< host << "\r\n";
        stream << "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\n";
        stream << "Content-Type:application/x-www-form-urlencoded\r\n";
        stream << "Content-Length:" << post_content.length()<<"\r\n";
        stream << "Connection:close\r\n\r\n";
        stream << post_content.c_str();
        socketHttp(host, stream.str());
    }
    void HttpConnect::getData(std::string host, std::string path, std::string get_content)
    {
        //GET请求方式
        std::stringstream stream;
        stream << "GET " << path << "?" << get_content;
        stream << " HTTP/1.0\r\n";
        stream << "Host: " << host << "\r\n";
        stream <<"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\n";
        stream <<"Connection:close\r\n\r\n";
        socketHttp(host, stream.str());
    }
    

     

        HttpConnect *http = new HttpConnect();
        http->getData("127.0.0.1", "/login", "id=liukang&pw=123");
        http->postData("127.0.0.1", "/login","id=liukang&pw=123");


    //***********************************
    C++实现简单http服务器
    只要懂socket套接字,http请求和响应的格式,就行了



    #include <winsock2.h>
    #include <string>
    #include <assert.h>
    #include <iostream>
    #pragma comment(lib,"ws2_32.lib")
    using namespace std;

    #define PORT 9999

    int main(){
        SOCKET sock;
        SOCKET connfd;
        WORD ver = MAKEWORD(2,2);//版本
        WSADATA dat;
        WSAStartup(ver, &dat);

        sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        if (sock == -1)
        {
            return false;
        }
        
        struct sockaddr_in sever_address;
        memset(&sever_address,0,sizeof(sever_address));
        sever_address.sin_family = AF_INET;
        sever_address.sin_addr.s_addr =htonl(INADDR_ANY);
        sever_address.sin_port = htons(PORT);

        int ret = bind(sock, (struct sockaddr*)&sever_address,sizeof(sever_address));
        assert(ret != -1);

        ret = listen(sock,10);
        assert(ret != -1);
        cout<<"wait\n";
        while (1)
        {
            struct sockaddr_in client_address;
            int len=sizeof client_address;
            connfd=accept(sock,(sockaddr*)&client_address,&len);
            char buf[1024];
            int n=recv(connfd,buf,sizeof buf,0);
            buf[n]='\0';
            printf("recv:\n%s\n",buf);
            char head[]="HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";

            string text1="<!DOCTYPE html>\n<html><head>\n<meta charset=\"gb2312\">\n<title>菜鸟教程(runoob.com)";
            string text2="</title>\n<body>\n<h1>我的第一个标题</h1>\n<p>我的第一个段落。</p>\n</body>\n</html>
    string text=text1+text2;
            
           send(connfd,head,strlen(head),0);
           send(connfd,text.c_str(),strlen(text.c_str()),0);
           printf("send:\n");
           cout<<head<<text<<endl;

           closesocket(connfd);
        }
        closesocket(sock);
        getchar();
    }

    //********************************

    C++ http服务器和客户端代码(无报文格式)
    服务器代码
        SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);
        int send_len = 0;
        int recv_len = 0;
        //定义服务端套接字,接受请求套接字
        SOCKET s_server;
        //服务端地址客户端地址
        SOCKADDR_IN server_addr;
        //初始化套接字库
        WSADATA wsadata;
        WSAStartup(0x22, &wsadata);    
        //填充服务端地址信息
        //填充服务端信息
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
        server_addr.sin_port = htons(80);
        std::string msgstr="";
        //创建套接字
        s_server = socket(AF_INET, SOCK_STREAM, 0);
        int result = bind(s_server,(struct sockaddr *) &server_addr,sizeof(server_addr));
        if (result == SOCKET_ERROR) /* 绑定失败 */
        {
            closesocket(s_server);
            printf("[Web] Fail to bind, error = %d\n", WSAGetLastError());
            return -1; 
        }
        if (listen(s_server,SOMAXCONN)==-1) {
            int err = GetLastError();
            std::cout << "服务器启动失败!" << std::endl;
            std::cout << err << std::endl;
        }
        else {
            std::cout << "服务器启动成功!" << std::endl;
        }
        while(1){
            SOCKADDR_IN from_addr;   /* 客户端地址  */
            socklen_t from_len = sizeof(from_addr);
            std::string reponse_data="404";
            SOCKET acpt_soc = accept(s_server,(struct sockaddr *) &from_addr,&from_len);
            if (acpt_soc == INVALID_SOCKET) /* 接受失败 */
            {    int err = GetLastError();
                printf("接收失败1", WSAGetLastError());
                std::cout << err << std::endl;
                break; 
            }
                char recv_buf [1025] = "";
                recv_len = recv(acpt_soc,recv_buf,1025, 0);
                if (recv_len < 0) {
                std::cout << "接收失败2!" << std::endl;
                }else{
                std::cout << "接收成功!" << std::endl;
                std::cout << recv_buf << std::endl;
                }
                send_len = send(acpt_soc,recv_buf,strlen(recv_buf), 0);
                if (send_len < 0) {
                    std::cout << "发送失败!" << std::endl;
                    closesocket(acpt_soc);
                }else{
                    std::cout << "发送成功!" << std::endl;
                }
        }
        //关闭套接字
        closesocket(s_server);
        //释放DLL资源
        WSACleanup();

    客户端代码
        SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);
            //printf("客户端嵌套字已经打开!\n");
        int send_len = 0;
        int recv_len = 0;
        //定义服务端套接字,接受请求套接字
        SOCKET s_server;
        //服务端地址客户端地址
        SOCKADDR_IN server_addr;
        //初始化套接字库
        WSADATA wsadata;
        WSAStartup(0x22, &wsadata);    
        //填充服务端地址信息
        //填充服务端信息
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
        server_addr.sin_port = htons(12580);
        string msgstr="";
        //创建套接字
        s_server = socket(AF_INET, SOCK_STREAM, 0);
        int nTimeout = 120000;
        //设置接收超时为1000ms
        if (SOCKET_ERROR == setsockopt(s_server, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTimeout, sizeof(int)))
        {
            fprintf(stderr, "Set SO_RCVTIMEO error !\n");
        }
        if (connect(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
            cout << "服务器连接失败!" << endl;
            closesocket(s_server);
            //释放DLL资源
            WSACleanup();
            return 0;
        }
        else {
            cout << "服务器连接成功!" << endl;
        }
        //发送,接收数据
            cout << "开始传输桌面信息:"<< endl;
        while(1){
                char send_buf [1025] = "111";
                send_len = send(s_server,send_buf,strlen(send_buf), 0);
                    if (send_len < 0) {
                        cout << "发送失败!" << endl;
                        closesocket(s_server);
                        //释放DLL资源
                        WSACleanup();
                        return 0;
                    }else{
                        cout << "发送成功!" << endl;
                    }
                    char recv_buf [1025] = "";
                    recv_len = recv(s_server,recv_buf,1025, 0);
                    if (recv_len < 0) {
                        cout << "接收失败!" << endl;
                        closesocket(s_server);
                        //释放DLL资源
                        WSACleanup();
                        return 0;
                    }else{
                        cout <<recv_buf<< endl;
                        cout << "接收成功!" << endl;
                    }
        }
        //关闭套接字
        closesocket(s_server);
        //释放DLL资源
        WSACleanup();

    //************************************
    C++实现简单的HTTP服务器

    #include <Winsock2.h> #include <windows.h> #include <malloc.h> #include <stdio.h> #include <string.h> #include <time.h> #pragma comment (lib,"ws2_32") #define uPort 80 #define MAX_BUFFER 100000 #define SENDBLOCK 200000 #define SERVERNAME "AcIDSoftWebServer/0.1b" #define FileName "HelloWorld.html" typedef struct _NODE_ { SOCKET s; sockaddr_in Addr; _NODE_* pNext; }Node,*pNode; //多线程处理多个客户端的连接 typedef struct _THREAD_ { DWORD ThreadID; HANDLE hThread; _THREAD_* pNext; }Thread,*pThread; pNode pHead = NULL; pNode pTail = NULL; pThread pHeadThread = NULL; pThread pTailThread = NULL; bool InitSocket();//线程函数 DWORD WINAPI AcceptThread(LPVOID lpParam); DWORD WINAPI ClientThread(LPVOID lpParam); bool IoComplete(char* szRequest); //数据包的校验函数 bool AddClientList(SOCKET s,sockaddr_in addr); bool AddThreadList(HANDLE hThread,DWORD ThreadID); bool ParseRequest(char* szRequest, char* szResponse, BOOL &bKeepAlive); //我们存放Html文件的目录 char HtmlDir[512]={0}; void main() { if (!InitSocket()) { printf("InitSocket Error\n"); return; } GetCurrentDirectory(512,HtmlDir); strcat(HtmlDir,"\\HTML\\"); strcat(HtmlDir,FileName); //启动一个接受线程 HANDLE hAcceptThread = CreateThread(NULL,0,AcceptThread,NULL,0,NULL); //在这里我们使用事件模型来实现我们的Web服务器 //创建一个事件 WaitForSingleObject(hAcceptThread,INFINITE); } DWORD WINAPI AcceptThread(LPVOID lpParam) //接收线程 { //创建一个监听套接字 SOCKET sListen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED); //使用事件重叠的套接字 if (sListen==INVALID_SOCKET) { printf("Create Listen Error\n"); return -1; } //初始化本服务器的地址 sockaddr_in LocalAddr; LocalAddr.sin_addr.S_un.S_addr = INADDR_ANY; LocalAddr.sin_family = AF_INET; LocalAddr.sin_port = htons(uPort); //绑定套接字 80端口 int Ret = bind(sListen,(sockaddr*)&LocalAddr,sizeof(LocalAddr)); if (Ret==SOCKET_ERROR) { printf("Bind Error\n"); return -1; } //监听 listen(sListen,5); //创建一个事件 WSAEVENT Event = WSACreateEvent(); if (Event==WSA_INVALID_EVENT) { printf("Create WSAEVENT Error\n"); closesocket(sListen); CloseHandle(Event); //创建事件失败 关闭套接字 关闭事件 return -1; } //将我们的监听套接字与我们的事件进行关联属性为Accept WSAEventSelect(sListen,Event,FD_ACCEPT); WSANETWORKEVENTS NetWorkEvent; sockaddr_in ClientAddr; int nLen = sizeof(ClientAddr); DWORD dwIndex = 0; while (1) { dwIndex = WSAWaitForMultipleEvents(1,&Event,FALSE,WSA_INFINITE,FALSE); dwIndex = dwIndex - WAIT_OBJECT_0; if (dwIndex==WSA_WAIT_TIMEOUT||dwIndex==WSA_WAIT_FAILED) { continue; } //如果有真正的事件我们就进行判断 WSAEnumNetworkEvents(sListen,Event,&NetWorkEvent); ResetEvent(&Event); // if (NetWorkEvent.lNetworkEvents == FD_ACCEPT) { if (NetWorkEvent.iErrorCode[FD_ACCEPT_BIT]==0) { //我们要为新的连接进行接受并申请内存存入链表中 SOCKET sClient = WSAAccept(sListen, (sockaddr*)&ClientAddr, &nLen, NULL, NULL); if (sClient==INVALID_SOCKET) { continue; } else { //如果接收成功我们要把用户的所有信息存放到链表中 if (!AddClientList(sClient,ClientAddr)) { continue; } } } } } return 0; } DWORD WINAPI ClientThread(LPVOID lpParam) { //我们将每个用户的信息以参数的形式传入到该线程 pNode pTemp = (pNode)lpParam; SOCKET sClient = pTemp->s; //这是通信套接字 WSAEVENT Event = WSACreateEvent(); //该事件是与通信套接字关联以判断事件的种类 WSANETWORKEVENTS NetWorkEvent; char szRequest[1024]={0}; //请求报文 char szResponse[1024]={0}; //响应报文 BOOL bKeepAlive = FALSE; //是否持续连接 if(Event == WSA_INVALID_EVENT) { return -1; } int Ret = WSAEventSelect(sClient, Event, FD_READ | FD_WRITE | FD_CLOSE); //关联事件和套接字 DWORD dwIndex = 0; while (1) { dwIndex = WSAWaitForMultipleEvents(1,&Event,FALSE,WSA_INFINITE,FALSE); dwIndex = dwIndex - WAIT_OBJECT_0; if (dwIndex==WSA_WAIT_TIMEOUT||dwIndex==WSA_WAIT_FAILED) { continue; } // 分析什么网络事件产生 Ret = WSAEnumNetworkEvents(sClient,Event,&NetWorkEvent); //其他情况 if(!NetWorkEvent.lNetworkEvents) { continue; } if (NetWorkEvent.lNetworkEvents & FD_READ) //这里很有意思的 { DWORD NumberOfBytesRecvd; WSABUF Buffers; DWORD dwBufferCount = 1; char szBuffer[MAX_BUFFER]; DWORD Flags = 0; Buffers.buf = szBuffer; Buffers.len = MAX_BUFFER; Ret = WSARecv(sClient,&Buffers,dwBufferCount,&NumberOfBytesRecvd,&Flags,NULL,NULL); //我们在这里要检测是否得到的完整请求 memcpy(szRequest,szBuffer,NumberOfBytesRecvd); if (!IoComplete(szRequest)) //校验数据包 { continue; } if (!ParseRequest(szRequest, szResponse, bKeepAlive)) //分析数据包 { //我在这里就进行了简单的处理 continue; } DWORD NumberOfBytesSent = 0; DWORD dwBytesSent = 0; //发送响应到客户端 do { Buffers.len = (strlen(szResponse) - dwBytesSent) >= SENDBLOCK ? SENDBLOCK : strlen(szResponse) - dwBytesSent; Buffers.buf = (char*)((DWORD)szResponse + dwBytesSent); Ret = WSASend( sClient, &Buffers, 1, &NumberOfBytesSent, 0, 0, NULL); if(SOCKET_ERROR != Ret) dwBytesSent += NumberOfBytesSent; } while((dwBytesSent < strlen(szResponse)) && SOCKET_ERROR != Ret); } if(NetWorkEvent.lNetworkEvents & FD_CLOSE) { //在这里我没有处理,我们要将内存进行释放否则内存泄露 } } return 0; } bool InitSocket() { WSADATA wsadata; if (WSAStartup(MAKEWORD(2,2),&wsadata)==0) //使用Socket前必须调用 参数 作用 返回值 { return true; } return false; } bool AddClientList(SOCKET s,sockaddr_in addr) { pNode pTemp = (pNode)malloc(sizeof(Node)); HANDLE hThread = NULL; DWORD ThreadID = 0; if (pTemp==NULL) { printf("No Memory\n"); return false; } else { pTemp->s = s; pTemp->Addr = addr; pTemp->pNext = NULL; if (pHead==NULL) { pHead = pTail = pTemp; } else { pTail->pNext = pTemp; pTail = pTail->pNext; } //我们要为用户开辟新的线程 hThread = CreateThread(NULL,0,ClientThread,(LPVOID)pTemp,0,&ThreadID); if (hThread==NULL) { free(pTemp); return false; } if (!AddThreadList(hThread,ThreadID)) { free(pTemp); return false; } } return true; } bool AddThreadList(HANDLE hThread,DWORD ThreadID) { pThread pTemp = (pThread)malloc(sizeof(Thread)); if (pTemp==NULL) { printf("No Memory\n"); return false; } else { pTemp->hThread = hThread; pTemp->ThreadID = ThreadID; pTemp->pNext = NULL; if (pHeadThread==NULL) { pHeadThread = pTailThread = pTemp; } else { pTailThread->pNext = pTemp; pTailThread = pTailThread->pNext; } } return true; } //校验数据包 bool IoComplete(char* szRequest) { char* pTemp = NULL; //定义临时空指针 int nLen = strlen(szRequest); //请求数据包长度 pTemp = szRequest; pTemp = pTemp+nLen-4; //定位指针 if (strcmp(pTemp,"\r\n\r\n")==0) //校验请求头部行末尾的回车控制符和换行符以及空行 { return true; } return false; } //分析数据包 bool ParseRequest(char* szRequest, char* szResponse, BOOL &bKeepAlive) { char* p = NULL; p = szRequest; int n = 0; char* pTemp = strstr(p," "); //判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。 n = pTemp - p; //指针长度 // pTemp = pTemp + n - 1; //将我们的指针下移 //定义一个临时的缓冲区来存放我们 char szMode[10]={0}; char szFileName[10]={0}; memcpy(szMode,p,n); //将请求方法拷贝到szMode数组中 if (strcmp(szMode,"GET")==0) //一定要将Get写成大写 { //获取文件名 pTemp = strstr(pTemp," "); pTemp = pTemp + 1; //只有调试的时候才能发现这里的秘密 memcpy(szFileName,pTemp,1); if (strcmp(szFileName,"/")==0) { strcpy(szFileName,FileName); } else { return false; } } else { return false; } // 分析链接类型 pTemp = strstr(szRequest,"\nConnection: Keep-Alive"); //协议版本 n = pTemp - p; if (p>0) { bKeepAlive = TRUE; } else //这里的设置是为了Proxy程序的运行 { bKeepAlive = TRUE; } //定义一个回显头 char pResponseHeader[512]={0}; char szStatusCode[20]={0}; char szContentType[20]={0}; strcpy(szStatusCode,"200 OK"); strcpy(szContentType,"text/html"); char szDT[128]; struct tm *newtime; long ltime; time(<ime); newtime = gmtime(<ime); strftime(szDT, 128,"%a, %d %b %Y %H:%M:%S GMT", newtime); //读取文件 //定义一个文件流指针 FILE* fp = fopen(HtmlDir,"rb"); fpos_t lengthActual = 0; int length = 0; char* BufferTemp = NULL; if (fp!=NULL) { // 获得文件大小 fseek(fp, 0, SEEK_END); fgetpos(fp, &lengthActual); fseek(fp, 0, SEEK_SET); //计算出文件的大小后我们进行分配内存 BufferTemp = (char*)malloc(sizeof(char)*((int)lengthActual)); length = fread(BufferTemp,1,(int)lengthActual,fp); fclose(fp); // 返回响应 sprintf(pResponseHeader, "HTTP/1.0 %s\r\nDate: %s\r\nServer: %s\r\nAccept-Ranges: bytes\r\nContent-Length: %d\r\nConnection: %s\r\nContent-Type: %s\r\n\r\n", szStatusCode, szDT, SERVERNAME, length, bKeepAlive ? "Keep-Alive" : "close", szContentType); //响应报文 } //如果我们的文件没有找到我们将引导用户到另外的错误页面 else { } strcpy(szResponse,pResponseHeader); strcat(szResponse,BufferTemp); free(BufferTemp); BufferTemp = NULL; return true; }

    复制代码

    展开全文
  • 简单邮件传输协议SMTP

    千次阅读 2018-05-11 15:46:15
    1. SMTP协议概述SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)是由源地址到目的地址传送邮件的一组规则,用来控制信件的中转方式。SMTP协议属于TCP/IP协议族,它使每台计算机在发送或中转信件时能...
  • 基于 Socket 和 HTTP协议实现简单的Web服务器

    万次阅读 多人点赞 2018-07-21 16:40:30
    本Web服务器能够实现的基本功能: 1、实现最基本的HTTP/1.0版本的web服务器,客户端能够使用GET、POST方法请求资源  ...3、服务器能进行简单的cgi程序·,能够根据 query_string或者 body中的内容动态生成页面。比...
  • Http协议与TCP协议简单理解

    万次阅读 多人点赞 2014-06-03 11:10:16
    在C#编写代码,很多时候会遇到Http协议或者TCP协议,这里做一个简单的理解。 TCP协议对应于传输层,而HTTP协议对应于应用层,从本质上来说,二者没有可比性。Http协议是建立在TCP协议基础之上的,当浏览器需要从...
  • 简单邮件传送协议SMTP

    千次阅读 2015-11-25 21:43:44
    简单邮件传送协议,简称SMTP(Simple Mail Transfer Protocol)。 一个电子邮件系统应具有三个主要组成构件,用户代理、邮件服务器、SMTP和POP3(注:POP3是邮局协议(Post Office Protocol)的版本3),如下图: ...
  • Http协议与TCP协议简单理解后续

    万次阅读 多人点赞 2016-09-05 08:58:52
    最近再次简单读了一遍《TCP/IP协议卷》,有了一些新的理解。这篇文章没有一个很好的连贯性,都是我在读书过程中总结的知识点,整体比较松散,但是个人感觉知识点都是非常重要,有很多地方让我明白了迷惑很久的问题。...
  • iOS Http协议与TCP协议简单理解

    千次阅读 2016-03-07 15:51:42
    在C#编写代码,很多时候会遇到Http协议或者TCP协议,这里做一个简单的理解。 TCP协议对应于传输层,而HTTP协议对应于应用层,从本质上来说,二者没有可比性。Http协议是建立在TCP协议基础之上的,当浏览器需要从...
  • 链路层链路发现协议(LLDP)讲解

    万次阅读 多人点赞 2015-06-24 10:59:11
    一、LLDP协议概述  随着网络技术的发展,接入网络的设备的种类越来越多,配置越来越复杂,来自不同设备厂商的设备也往往会增加自己特有的功能,这就导致在一个网络中往往会有很多具有不同特性的、来自不同厂商的...
  • HTTP协议其实就是这么简单

    万次阅读 多人点赞 2018-05-03 11:49:02
    一、HTTP简介1.http协议介绍HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。HTTP是基于TCP/IP通信协议来传递数据(HTML ...
  • ssh协议简单介绍

    万次阅读 2014-10-13 10:44:19
    也就是说,SSH协议要求每一个使用本协议的主机都必须至少有一个自己的主机密钥对,服务方通过对客户方主机密钥的认证之后,才能允许其连接请求。一个主机可以使用多个密钥,针对不同的密钥算法而拥有不同的密钥,...
  • 嵌入式Web服务器学习之HTTP协议

    千次阅读 2014-04-10 22:42:25
    它是一个请求、响应协议。当客户端发送出一个请求,服务器响应这个请求。HTTP运用可靠的TCP连接,通常用的80端口。 1.1 HTTP协议特点 (1) HTTP协议是无状态的,同一个客户端的这次请求和上次请
  • MySQL客户端与服务器协议

    千次阅读 2013-09-26 13:12:22
     1、监听tcp协议之上  2、握手验证先行  3、Command in one packet,Responses may in several. 包(packet)格式  压缩与非压缩,取决于握手阶段,客户端与服务器协商  抛开压缩项,包分为两种:客户端请求与...
  • Qt TCP协议 传输简单字符串实例

    千次阅读 2016-08-22 10:06:49
    Qt TCP协议 传输简单字符串实例是本文要介绍的内容。TCP即Transmission Control Protocol,传输控制协议。与UDP不同,它是面向连接和数据流的可靠传输协议。也就是说,它能使一台计算机上的数据无差错的发往网络上的...
  • 浏览器访问服务器的过程 1/用户输入网址 2/浏览器请求DNS服务器,获取...4/发送资源请求(HTTP协议) 5/web服务器接收请求,并解析请求,判断用户意图 6/获取用户想要的资源. 7/将资源返回给web服务器程序...
  • Python实现简单的Web服务器

    万次阅读 2019-03-29 00:15:28
    Python实现简单的Web服务器项目来源知识储备:HTTP的了解开始项目hello,web——我的第一个web服务器 项目来源 本课程核心部分来自500 lines or less项目,作者是 Mozilla 的 Greg Wilson。项目代码使用 MIT 协议,...
  • Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案,比如 Airbnb的SmartStack等相比,Consul的方案更“一站式”,内置了服务注册与发现框 架、分布一致...
  • Qt Http服务器简单变成https服务器

    千次阅读 2018-05-11 18:05:10
    一开始qt http服务器还是好简单,因为就是TCP连接上面一个简单协议。后来听说发布小程序必须用到https+域名,估计好多刚开始往小程序里跑的小伙子都哭晕在测所。不过我不负责写小程序,我负责搞用qt 写个http的...
  • 了解MQTT协议以及利用Netty搭建MQTT服务器MQTT协议协议简介设计原则灵活的发布订阅和主题设计带宽消耗最小化三个可选的 QoS 等级会话保持在线状态感知开源 MQTT 服务器MQTT 发布订阅模式介绍发布订阅模式消息路由...
  • socks代理服务器协议的说明

    千次阅读 2017-05-11 15:51:11
    转自:... socks代理里面,有socks4 socks4a socks5,也有叫sock4 sock4a sock5的,都是一回事。 socks4 socks4a和socks5的tcp部分极其简单。 这又出现一个怪现象了,网文中除了一个人说道udp比...
  • MQTT协议简介及协议原理

    千次阅读 2020-06-13 15:24:00
    带你看看MQTT协议简介及协议原理
  • Web服务器的工作原理及其相关协议

    千次阅读 2016-04-21 16:52:30
    WEB服务器也称为WWW(WORLD WIDE WEB)服务器,主要功能是提供网上信息浏览服务。 通俗的说,Web服务器是可以向发出请求的浏览器提供文档的程序。 1、服务器是一种被动程序:只有当Internet上运行在其他计算机中的...
  • syslog协议及rsyslog服务全解析

    千次阅读 2017-11-13 22:43:32
    背景:需求来自于一个客户想将服务器的日志转发到自己的日志服务器上,所以希望我们能提供这个转发的功能,同时还要满足syslog协议。 一、什么是syslog协议 1、介绍(略) 2、syslog标准协议如下图 ...
  • Java实现简单的FTP服务器

    千次阅读 2016-08-17 18:21:28
    遇到的问题前言学习了Java网络编程了,为了检验自己的学习程序和熟悉相关的知识点,为此,使用Java Socket编程实现了一个简单的FTP服务器。以下记录了自己整个开发的流程。FTP协议自己平时也有用过ftp协议进行文件的...
  • 标签: 服务器浏览器sessionservlet文档web服务 2012-04-26 17:48 12966人阅读 评论(2) 收藏 举报  分类: C# ASP.NET(137)  目录(?)[+]  http协议学习系列 1. 基础概念篇
  • java实现简单web服务器(分析+源代码)

    千次阅读 多人点赞 2014-05-03 21:45:29
    在日常的开发中,我们用过很多开源的web服务器,例如tomcat、apache...web服务基于的是HTTP协议,用户在浏览器的地址栏输入要访问的地址,服务器如何得到该地址是个关键。先看下一般的HTTP请求和响应报文的一般格式:
  • 使用SSL协议保证web服务通信安全

    千次阅读 2012-10-12 10:32:14
    因此,本文就将对SSL协议进行深入剖析,并介绍如何使用SSL技术保护Apache服务器通信。 1 SSL简介 通常的连接方式中,通信是以非加密的形式在网络上传播的,这就有可能被非法窃听到,尤其是用于认证的口令信息...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 139,179
精华内容 55,671
关键字:

如何关闭简单服务发现协议