• socket模块--TCP和UDP协议下的基础网络通话


    一、什么是socket:

    套接字socket: 在python中就是一个模块, socket是在应用层与传输层中间的抽象层.
        socket就像是一个接口,通过这个接口可以实现网络通信.  
    它把复杂的TCP/IP协议族隐藏在Socket接口后面,socket屏蔽了各个协议的通信细节,使得程序员无需关注协议本身,直接使用socket提供的接口来进行互联的不同主机间的进程的通信。

     socket根据用途,有两种分类:

    1)基于文件类型的套接字家族:AF_UNIX, 基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
    2)基于网络类型的套接字家族(AF_INET):网络编程就是用的 AF_INET

    osi七层模型:  互联网的核心就是由一堆协议组成,协议就是标准,标准就是大家都认可的,下面的图是数据通过网络沟通经过的底层细节.主要记住五层就够了

     socket 在网络流程中的位置:应用层与传输层之间

    简述访问Jd网站流程

    我的计算机首先提交访问某域名的请求,通过dns服务器(有一个字典,域名对应着IP)它将域名转化成ip地址返回给我的计算机
    我的计算机通过ip协议和子网掩码判断出不在一个局域网后,提交给交换机,然后交换机提交给路由器,路由器带着的源ip地址和源mac地址以及目标的源ip地址和端口,通过nat技术将我的计算机虚拟IP(局域网IP)转换成公网IP,在经过路由协议,优化出最短的访问路径,访问到对应的路由器上的,然后对应的路由器通过端口映射技术访问到目标IP的端口上.(内网的IP,因为是虚拟的,所以外部是访问不到的,只能访问到公网IP,像Jd类的大公司,都会买一个公网IP,所以我们才能直接访问到)

    二、基于TCP和UDP两个协议下的socket的通讯流程

    什么是TCP: 可靠的、面向连接的协议,传输效率低全双工通信(发送缓存&接收缓存)、面向字节流. 比如:Web浏览器,文件传输程序。

    什么是UDP:不可靠的、面向无连接的服务,传输效率高(发送前时延小),既可多对多,也可一对多,无拥塞控制,面向报文(以包的形式发送). 比如:域名系统 (DNS),视频流,IP语音(VoIP)。

     tcp的连接需要经过三次握手,断开需要经过四次挥手:

     UDp的连接和断开不需要三握和四挥.

    网络传输ios五层流程图:

    pycharm里面默认用的是网络家族的TCP(字节流数字流)协议

    三、基于UDP协议下的socket网络通话.(type=cocket.SOCK_DGRAM)可以多人连接通话   datagram(数据包)

    UDP协议下不会产生粘包现象,因为有消息边界,每次发送,都是以包的形式发送(有包头和消息组成),对方取值是,如果取值的"勺子"(recvfrom(n)的参数)设置的太小,就会出异常;
    当太大时,一次只会取一个包.所以不会出现粘包现象.

    UDP服务端:这里的recvfrom(1024)是UDP特有;TCP是recv(1024)设置从缓存取每次取值的大小,单位为字节)

    UDP客户端:

     四、TCP通话(允许多人通话,但需要排队,跟一个客户端了之后才能跟下一个客户连接.),服务端:(addr是地址的缩写)

    import socket  #建立网络通信的模块
    xiaoli = socket.socket()
    xiaoli.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    ip_xiaoli = ("127.0.0.1",8001)
    xiaoli.bind(ip_xiaoli)
    #侦听ip地址和端口,简称开机
    xiaoli.listen(3) #默认为1,连接一个通道,可以配置,表示连接一个通道后,允许其他对象重用我的IP地址进行通话,但需排队等待
    while 1:
        # 等待建立连接, conn是连接通道,addr是客户端的地址
        conn,addr=xiaoli.accept()
        print(addr) #查看客户端地址
        while 1:
            # 服务端通过conn连接通道来收发消息,通过recv方法,recv里面的参数是字节(B),1024的意思1024B=1KB
            kehu_xiaoxi = conn.recv(1024).decode("utf-8")
            print("客户端告诉你>>>",kehu_xiaoxi)
            if kehu_xiaoxi=="byebye":
                break
            # 回复消息:通过send方法,参数必须是字节类型的,
            tiwen = input("请输入内容:").encode("utf-8")
            conn.send(tiwen)
        conn.close()

     TCP多人通话,客户端:(#客户端的设置比服务端简单,省去了:侦听IP地址和设置消息通道,发送消息直接用实例对象.recv就行)

    import socket
    xiaohei = socket.socket()
    #连接服务端的应用程序,通过connect方法,参数是服务端的ip地址和端口,打电话
    xiaohei.connect(("127.0.0.1",8001))  
    while 1:
        tiwen1 = input("输入你想说的话:")
        xiaohei.send(tiwen1.encode("utf-8"))
        if tiwen1=="byebye":
            break
        duixiang = xiaohei.recv(1024).decode("utf-8")
        print("服务端说>>>",duixiang)
    xiaohei.close()

     五、小练习:TCP客户端每个2秒发送一条时间戳给TCP服务端,TCP服务端吧它转换成格式化时间.

    TCP服务端:

    TCP客户端(time sleep(t) 函数推迟调用线程的运行,可通过参数secs指秒数,表示进程挂起的时间,t -- 推迟执行的秒数)

     

  • 相关阅读:
    【CSS】带箭头的二级菜单页面
    golang写入Excel并设置样式
    golang之xorm简单使用
    golang全局变量的一个坑,main中无法获取init初始化的变量
    golang influxdb2读写封装
    将本地导入的jar包添加到maven中
    电脑天才郭盛华,如今怎样了?
    黑客在云环境中寻找攻击路径
    联想 UEFI 固件漏洞影响超100万台笔记本电脑
    IDEA的热部署
  • 原文地址:https://www.cnblogs.com/lgw1171435560/p/10216981.html
Copyright © 2020-2023  润新知