假期(网络编程)

"""
一、客户端/服务端架构:
    1、硬件C/S架构(打印机)
    2、软件C/S架构
        互联网中处处都是CS架构,服务端与客户端
    CS架构与socket的关系
        - 我们学习socket就是为了完成C/S架构的开发

二、OSI七层模型:
    一个完整的计算机系统是由硬件、操作系统、应用软件三者组成,一台计算机只能自己玩自己,要想跟别人玩就需要上网了
    互联网的核心就是由一堆协议组成,协议就是标准,比如全世界人通信的标准是英语;
    如果把计算机比做人,那么互联网协议就是计算机界的英语了,如果所有的计算机都学会了这门英语,那么就可以互相通信了
    为何学习socket一定要先学习互联网协议:
        - 1、首先我们的目标是基于socket编程,来开发一款自己的cs架构软件
        - 2、其次cs架构软件(软件属于应用层)是基于网络进行通信的
        - 3、网络的核心即一堆协议,协议即标准,你想开发一款基于网络通信的软件,就必须遵循这些标准

三、socket层
    socket层位于运输层和应用层之间,即socket抽象层

四、socket是什么?
    socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,socket其实就是一个门面模式,它吧复杂的
    TCP/IP协议族隐藏在了socket接口的后面,对用户来说,一组简单的接口就是全部,让socket去组织数据,以符合指定的协议
    所以我们无需深入理解tcp/udp协议,socket已经帮我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然符合标准
    - 也有人将socket说成是IP+port,IP是用来标识互联网中的一台主机的位置,而port是用来标识这台主机上的一个应用程序,IP地址
      配置到网卡上的,而port是应用程序开启的,IP与port的绑定就标识了互联网中独一无二的应用程序
      程序的pid是同一台机器上不同进程或者线程的标识

五、套接字的分类:
    - 基于文件类型的套接字家族
        套接字家族的名字:AF_UNIX
        unix一切皆文件,基于文件的套接字调用的就是底层文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个
        间接完成通信。
    - 基于网络类型的套接字家族
        套接字家族的名字:AF_INET
        ···所有的地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以我们
        大部分时间都只是使用AF_INET

六、套接字的工作流程:
    一个生活中的场景:你要给你前对象打电话,先拨号,前对象听到电话铃声后拿起电话,这时候你俩就建立起来了不正当的链接,然后
    就可以进行不正当的交易了。交易完成后,挂断电话结束此次交谈;
    先从服务端说起,服务端先初始化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 xxx import * 的语句导入,这样就可以减少代码量
        eg:tcpsock = socket(AF_INET,SOCK_STREAM)
    - 服务端套接字函数
        s.bind()绑定(主机,端口号)到套接字
        s.listen()开始tcp监听
        s.accept()被动接受tcp客户的连接,(阻塞式)等待连接的到来
    - 客户端套接字函数
        c.connect()被动初始化tcp服务器连接
        c.connect_ex() connect()函数的扩展版本,出错时返回错误码,而不是抛出异常
    - 公共用途的套接字函数
        s.recv()接受tcp数据
        s.send()发送tcp数据(send在待发送数据量大于已缓存区剩余的空间时,数据丢失,不会发完)
        s.sendall()发送完整的tcp数据(本质就是循环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服务端:
        server = socket()   #创建服务器套接字
        server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
        server.bind()       #把地址绑定到套接字
        server.listen()     #监听链接
        while true:         #服务器无限循环
            client,addr = server.accept()    #接受客户端链接
            while True:                 #通信循环
                client.recv()/client.send()   #接收与发送数据
            client.close()  #关闭客户端套接字
        server.close()       #关闭服务器套接字
    - tcp客户端:
        client = socket()    #创建客户端套接字
        client.connect()     #尝试链接服务器
        while True:
            client.send()/client.recv()   #发送/接收数据
        client.close()      #关闭客户端套接字

八、基于udp的套接字
    - udp服务端
        server = socket()     #创建服务器套接字
        server.bind()         #绑定套接字地址
        while True:           #服务器无线循环
            client,addr = server.recvfrom()/server.sendto()    #接收与发送数据
        server.close()     #关闭服务器套接字
    - udp客户端
        client = socket()      #创建客户端套接字
        while True:            #通信循环
            client.sendto()/client.recvfrom()    #发送与接收数据
        client.close()  #关闭客户端套接字

九、粘包现象(了解)
    如果当我们用socket模拟cmd执行远程命令时,有些数据太长,超过了1024个字节,一次接受不完,就会造成粘包
    - 什么是粘包?
        只有tcp才有粘包现象,udp永远不会粘包,因为udp是基于流收发数据的
        所谓粘包的问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少数据造成的
    - 粘包的解决
        - struct模块
        - 自定义报头
        - ···
    - 什么时候才会发生粘包?
        发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据很小会喝到一起,产生粘包)
        接收方不及时接收缓冲区的包,造成多个包接收产生粘包
    - 了解
        tcp是可靠传输,udp是不可靠传输

十、socketserver模块
    - 终极必杀技






















"""
原文地址:https://www.cnblogs.com/52-qq/p/8449470.html