Python Day29 网络协议

~为何学习socket一定要先学习互联网协议:

1.首先:本节课程的目标就是教会你如何基于socket编程,来开发一款自己的C/S架构软件

2.其次:C/S架构的软件(软件属于应用层)是基于网络进行通信的

3.然后:网络的核心即一堆协议,协议即标准,你想开发一款基于网络通信的软件,就必须遵循这些标准。

 ~~~~

                   ===== 互联网协议  osi七层协议 =====

    应用层 + 传输层 + 网络层 + 网络接口层               4层
    应用层 + 传输层 + 网络层 + (数据链路层+物理层)       5层
    (应用层 + 表示层 + 会话层)+ 传输层 + 网络层 + (数据链路层+物理层)  7层

1) 物理层 ----- 硬件的标准----   >>>  发送电信号------对应数字 0,1


2) 数据链路层 ----以太网协议  ethernet  (根据物理层的信号 分组)       mac地址===>>> 局域网的地址
           一组电信号 构成一个数据包(帧) ---每一帧: head(接受者是谁 + 发送者是谁 + 数据类型) + data

            mac 地址:ethernet规定 internet设备 都必须有网卡---mac地址(发送 接收端的地址)
            广播: ethernet 通过 广播的方式通信
            广播包  只能在一个局域网内通信


3) 网络层----  ip 协议 (ipv4  ipv6)                              ip地址===>>> 确认子网地址

             ipv4 与 子网掩码  二进制---按位与运算(前三段一样)
             172.16.10.1(点分十进制) + 255.255.255.0 --->> 172.16.10.0 (子网的地址 范围)

            不在一个地址 把包传给网关 是一个 出口 (相当海关于) -- 跨子网通信 ---路由协议

            ARP 协议(ip找到mac)-----   把   ip地址  转换为一个  网关地址 ----方便子网内  mac广播通信

                                                              ip+mac ==== >>>  唯一的一台机器

4) 传输层 -----  传输层功能:建立端口到端口的通信  (包 传输头)  ()
                 标识这台主机上的应用程序,就是端口,端口即应用程序与网卡关联的编号
                 ip + 端口 --->> 唯一的软件

              用户应用层的内存中的数据 --->> 操作系统内存中 --->> 网卡 ----发送

              双向连接---那端的数据输完--可以先断掉
                tcp 协议  ----   可靠协议---建立连接3次握手 -----数据传输玩---客户端响应
                                断开连接4次挥手 --
                udp 协议  ----  不可靠协议


5) 应用层 ------应用层产生数据---数据包  (包一个 应用层头)

                        应用层功能:规定应用程序的数据格式

                       发数据---封包     ------

~~~~

 socket.SOCK_STREAM  流式socket , for TCP (默认)
  socket.SOCK_DGRAM   数据报式socket , for UDP

  socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
  socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
  socket.SOCK_SEQPACKET 可靠的连续数据包服务

****区别:

SOCK_STREAM   是有保障的(即能保证数据正确传送到对方)面向连接的SOCKET,多用于资料(如文件)传送。


SOCK_DGRAM   是无保障的面向消息的socket , 主要用于在网络上发广播信息。


SOCK_STREAM是基于TCP的,数据传输比较有保障。SOCK_DGRAM是基于UDP的,专门用于局域网,基于广播


SOCK_STREAM 是数据流,一般是tcp/ip协议的编程,SOCK_DGRAM分是数据包,是udp协议网络编程


解释一下:
关于UDP
1、UDP协议适用端口分辨运行在同一台设备上的多个应用程序,UDP有不提供数据报分组、组装和不能对数据包进行排序的缺点。
也就是说,当报文发送之后,是无法得知其是否安全完整到达的。
2、在网络质量令人不十分满意的环境下,UDP协议数据包丢失会比较严重。
3、但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。


关于TCP
1、TCP提供端到端、全双工通信;采用字节流方式,如果字节流太长,将其分段;提供紧急数据传送功能。
2、TCP特性:
(1)面向连接的传输;   
(2)端到端的通信;   
(3)高可靠性,确保传输数据的正确性,不出现丢失或乱序;   
(4)全双工方式传输;   
(5)采用字节流方式,即以字节为单位传输字节序列;   
(6)紧急数据传送功能。


如果需要传输的数据是准确的,建议采用TCP,也就是SOCK_STREAM 
如果你传输的是视频音频等数据,丢几个包也无所谓的,可以采用UDP,也就是SOCK_DGRAM

一、socket层

二、socket是什么

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。

 三、套接字工作流程

  一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。 生活中的场景就解释了这工作原理。

先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束

~~~socket()模块函数用法

import socket
socket.socket(socket_family,socket_type,protocal=0)
socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,默认值为 0。

获取tcp/ip套接字
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

获取udp/ip套接字
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

由于 socket 模块中有太多的属性。我们在这里破例使用了'from module import *'语句。使用 'from socket import *',我们就把 socket 模块里的所有属性都带到我们的命名空间里了,这样能 大幅减短我们的代码。
例如tcpSock = socket(AF_INET, SOCK_STREAM)
服务端套接字函数
s.bind() 绑定(主机,端口号)到套接字
s.listen() 开始TCP监听
s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来

客户端套接字函数
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数
s.recv() 接收TCP数据
s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
s.sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
s.recvfrom() 接收UDP数据
s.sendto() 发送UDP数据
s.getpeername() 连接到当前套接字的远端的地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回指定套接字的参数
s.setsockopt() 设置指定套接字的参数
s.close() 关闭套接字

面向锁的套接字方法
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间

面向文件的套接字的函数
s.fileno() 套接字的文件描述符
s.makefile() 创建一个与该套接字相关的文件

三、基于TCP的套接字

tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端

tcp服务端:

ss = socket() #创建服务器套接字
ss.bind()      #把地址绑定到套接字
ss.listen()      #监听链接
inf_loop:      #服务器无限循环
    cs = ss.accept() #接受客户端链接
    comm_loop:         #通讯循环
        cs.recv()/cs.send() #对话(接收与发送)
    cs.close()    #关闭客户端套接字
ss.close()        #关闭服务器套接字(可选)

tcp客户端:

1 cs = socket()    # 创建客户套接字
2 cs.connect()    # 尝试连接服务器
3 comm_loop:        # 通讯循环
4     cs.send()/cs.recv()    # 对话(发送/接收)
5 cs.close()            # 关闭客户套接字

 





原文地址:https://www.cnblogs.com/liuduo/p/7593014.html