一、什么是socket:

 

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

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

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

 

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

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

 

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

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

 

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

简述访问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的连接需要经过三次握手,断开需要经过四次挥手:

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

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

 

网络传输ios五层流程图:

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

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

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

 

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

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

 

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

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

UDP客户端:

socket模块--TCP和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服务端:

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

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

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

 

分类:

技术点:

相关文章: