首页 > 其他分享 >TCP\UDP协议 socket模块

TCP\UDP协议 socket模块

时间:2022-11-16 17:01:42浏览次数:45  
标签:协议 UDP socket sock TCP 服务端 客户端

目录

传输层主要协议

传输层有很多协议,比如TCP、UDP协议。
TCP与UDP都是用来规定通信方式的
	通信的时候可以随心所欲的聊 也可以遵循一些协议符合要求的聊
  	随性所欲的聊:文字 图片 视频 小油腻话 你侬我侬
  	遵循一些协议:开头带尊称 首行空两格 只准用官话 不能打情骂俏
ps:不遵循上述协议也可以通信 只不过遵循了更合规合法合理!!!

TCP协议

TCP协议也称为流式协议、可靠协议(数据不容易丢失)

三次握手

  1. 经过这两步:C朝S建立了通道,这个通道是单向的,C可以给S发数据!
    image
  2. 如果S想给C发数据怎么办?又要走两步!才能建立S到C的通道。
    image
    注意:C给S发信息就走通道1,S给C发信息走通道2,这两个通道互不干扰!两个通道都是单向的!
  3. 这不是四次吗?为什么说是三次握手?
    因为中间两次可以整合为一次,也就是两条信息一起发了!总得来说只需要通信三次!这就是三次握手 建链接!
    image
    附上图片:
    image

TCP协议反馈机制

TCP协议之所以比UDP协议可靠 是建立了双向通道 对吗?

TCP协议之所以比UDP协议可靠 原因在与TCP协议发送消息有反馈机制!
(你必须要回复说,你收到了。如果你不回复,我就再次给你发同一份数据!)
基于TCP发送的消息会在本地先保存该消息 如果地方确认收到才会删除 否则在一定的时间内会频繁的多次发送直到确认或者超时为止。
我发给你一份 内存里也临时存一份 当你不回复,我隔个5秒10秒再给你发,如果我坚持给你发了30分钟,你都不回复,我就默认你嗝屁了, 就把临时保存的数据删掉。
另外当你回复:收到了! 我也会把内存里临时存的数据删掉。
# 也就是需要一个确认 确认通过了才会继续发 这就是反馈机制。

四次挥手

由任意一方发起断开的请求:如图C发送断开的请求,C同意。所以将会断开C到S的通道。
image
再经历两步,断开S到C的通道:
image
中间的两步为什么不能合并?
因为C已经没有数据给S了 ,但是S可能还有一些数据需要给C,服务器要确认自己的信息是否发完(TIME_WAIT)。所以S需要一个缓冲时间,无法立刻做出断开通道的决定,这中间是有一个检查时间(缓冲时间)的!

image
隐喻:

# 三次握手
男:做我女朋友!(建立链接)
女:同意!你也做我男朋友!(同意建立,并发起请求)
男:同意!(同意建立)

# 四次挥手
女:分手吧!(不跟你发消息)
男:同意,分手之后做朋友(还跟你发消息)
男:算了吧,还是别联系(断开请求)
女:6 (同意断开)

洪水攻击

洪水攻击:同一时间有大量的客户端请求建立链接 会导致服务端一直处于SYN_RCVD状态
如何抵御洪水攻击?建立半连接池

服务端如何区分客户端建立链接的请求:
1.通过ip
2.通过SYN 如SYN seq=x
x y表示不同客户端、服务端的唯一标识。

UDP协议

# UDP协议 
丢包协议、不可靠协议
彼此之间不做任何的链接 不做通道 不二次做确认操作
特点:不需要建立双向通道 数据的传输速度快 但是可能会丢失

qq使用的就是UDP协议 所有可能会丢失
但是我们可以在UDP协议的基础之上做很多额外的扩展来保证数据的安全

'''
TCP协议类似于打电话:你一句我一句 你侬我侬
UDP协议类似于发短信:发了之后不管你看不看 只要发了就行
'''

socket模块

# 编写一个CS架构的程序 实现数据交互
思考:
需要编写代码 操作OSI七层 相当复杂!
就跟操作系统 编写操作硬件的代码一样 
由于操作OSI七层 是所有CS架构的程序都需要经历的过程 所以为了方便 产生了socket技术。
在OSI七层中增加了socket抽象层,用socket提供的快捷方式操作其他层

image

python中socket模块>>>为操作OSI七层协议提供了快捷方式 不需要自己处理一遍

socket也叫套接字,有以下两种分类:
   基于文件类型的套接字家族(单机)
  	AF_UNIX
   基于网络类型的套接字家族(联网)
  	AF_INET

socket代码简介

'''服务端'''
import socket


"""
以后要养成查看源码编写代码的思路
"""
# 1.产生一个socket对象并指定采用的通信版本和协议(TCP)
server = socket.socket()  # 括号内不写参数 默认就是TCP协议  family=AF_INET基于网络的套接字 type=SOCK_STREAM流式协议即TCP
# 2.绑定一个固定的地址(服务端必备的条件)
server.bind(('127.0.0.1', 8080))  # 127.0.0.1为本地回环地址 只有自己的电脑可以访问
# 3.设立半连接池(暂且忽略)
server.listen(5)
# 4.等待接客
sock, addr = server.accept()  # return sock, addr  三次握手
print(sock, addr)  # sock就是双向通道 addr就是客户端地址
# 5.服务客人
data = sock.recv(1024)  # 接收客户端发送过来的消息 1024字节
print(data.decode('utf8'))
sock.send('尊敬的客人 您说什么就是什么 一切按照您的要求来'.encode('utf8'))  # 给客户端发送消息 注意消息必须是bytes类型
# 6.关闭双向通道
sock.close()  # 四次挥手
# 7.关闭服务端
server.close()  # 店倒闭了


'''客户端'''
import socket


# 1.生成socket对象指定类型和协议
client = socket.socket()
# 2.通过服务端的地址链接服务端
client.connect(('127.0.0.1', 8080))
# 3.直接给服务端发送消息
client.send('大爷有钱 把你们店最好的给我叫出来'.encode('utf8'))
# 4.接收服务端发送过来的消息
data = client.recv(1024)
print(data.decode('utf8'))
# 5.断开与服务端的链接
client.close()

socket.socket()

查看源码:
image

socket.socket()  # 会产生一个sockct对象
# 默认情况下socket对象 ---> TCP + 网络型套接字
family = AF_INET  # AF_INET的意思就是 基于网络的socket
type = SOCK_STREAM  # SOCK_STREAM 流式协议 也就是TCP协议 

server.bind()

查看源码:
image

server.bind(('127.0.0.1', 8080))
'''
bind方法用于给服务端绑定一个固定的地址
接受一个元祖 (IP地址,端口号)
'''

server.accept()

sock, addr = server.accept()  # return sock, addr
'''
accept有两个返回值:
sock表示客户端和服务端之间的管道 可以使用sock对象发送信息等
addr是访问服务端的客户端IP地址

addr是给你打电话的人的地址
sock是电话的听筒 你可以基于听筒跟别人交流!

如果没有客人上门 accept这行代码会一直等待 程序会卡在这里(listen)。
'''

sock.recv() sock.send()

sock.recv(1024)  # 接受
sock.send()   # 发送
'''
recv方法用于接收客户端发送过来的消息 如果 没有消息 或者 消息为空 程序都会卡这行代码
这里的数字1024 表示接受1024个字节 多了就抛弃
注意发送和接受的都是bytes类型 要对输入进行转码
'''

sock.close() server.close()

sock.close()  # 关闭通道
server.close()  # 关闭服务端
这两行代码也可以不写 因为socket模块有自动关闭的操作。

client.connect()

client.connect(('127.0.0.1',8080))  
'''
connect方法用于服务端链接客户端
传入一个元祖:(要访问的服务端IP,服务端端口号)'''

问题和优化

1.聊天内容自定义
针对消息采用input获取
2.让聊天循环起来
将聊天的部分用循环包起来

用户输入的消息不能为空

本质其实是两边不能都是recv或者send 一定是一方收一方发
相当于两边电话通了,但是都不说话,都在等着别人说话= =

服务端多次重启报错

Address already in use 主要是mac电脑会报
解决1:改C/S双方使用的端口号
解决2:加代码
添加如下红框代码:
image

#加入一条socket配置,重用ip和端口
import socket
from socket import SOL_SOCKET,SO_REUSEADDR
sk = socket.socket()
sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
sk.bind(('127.0.0.1',8898))  #把地址绑定到套接字
sk.listen()          #监听链接
conn,addr = sk.accept() #接受客户端链接
ret = conn.recv(1024)   #接收客户端信息
print(ret)              #打印客户端信息
conn.send(b'hi')        #向客户端发送信息
conn.close()       #关闭客户端套接字
sk.close()        #关闭服务器套接字(可选)

客户端异常断开

当客户端异常断开的情况下 如何让服务端继续服务其他客人?
客户端如果异常断开 服务端代码应该重新回到accept等待新的客人!
如果是windows电脑 停掉客户端 服务端会直接报错
如果是mac、linux则不会报错 服务端会接受到一个空消息。
所以对mac、linux:
image
如果是window,则需要异常处理,捕获到因为服务端断掉而产生的报错:
但是服务端也无法继续服务客户了,还是没回到accept,所有只能再套一个循环:
image

半连接池

当有多个客户端来链接的情况下 我们可以设置等待数量(不考虑并发问题)

server.listen

server.listen(5) 
'''
用于构造半连接池
比如海底捞排队 给门外摆了5把椅子
'''

示例

使得一个py文件可以运行多次:
image
让多个服务端和客户端产生链接:
image
绿色的框内有:1个正在被服务的客人 5个在椅子上等待的客人
红色框:2个被拒之门外的客人
image
如果在报错之前 有客人退出 则会有椅子空出 也就能再坐一个人。

标签:协议,UDP,socket,sock,TCP,服务端,客户端
From: https://www.cnblogs.com/passion2021/p/16896060.html

相关文章

  • socket 模块
    socket模块我们知道基于网络编写程序时,需要使用OSI七层协议里的七层,每一层都要写。很复杂很繁琐。socket模块相当于集成了这一块,封装了复杂的接口提空了简单快捷的接......
  • 传输层之TCP与UDP协议、socket
    目录传输层之TCP与UDP协议应用层socket模块Socket通信socket代码简介代码优化半连接池的概念传输层之TCP与UDP协议TCP与UDP都是用来规定通信方式的ps:不遵循上述协议也......
  • 关于 WebSocket 和 HTTP 区别的思考以及一个最简单的 WebSocket 的客户端和服务器实现
    笔者之前与一位同事研究了Cypress的visit方法,其源码实现最终是调用了WebSocket向visit参数里指定的website通行并获取数据,见下图变量ev.data的值。我这位同......
  • socket模块简介
    今日内容概要传输层只TCP与UDP协议应用层socket模块简介socket模块基本使用代码优化处理半连接池的概念今日内容详细传输层只TCP与UDP协议TCP与UDP都是用来......
  • socket
    目录今日内容概要今日内容详细传输层之TCP与UDP协议应用层socket模块socket代码简介代码优化半连接池的概念今日内容概要传输层之TCP与UDP协议应用层socket模块简介s......
  • docker报错Got permission denied while trying to connect to the Docker daemon soc
    报错内容GotpermissiondeniedwhiletryingtoconnecttotheDockerdaemonsocketatunix:///var/run/docker.sock:Get"http://%2Fvar%2Frun%2Fdocker.sock/v1.......
  • fastapi socketio
    E:\song\agv_fastapi_socket2\fastapi-socketio-example-main\app.pyimportosimportpathlibimportsecretsimporttimefromtypingimportOptionalimportsocket......
  • Linux下Socket编程(转)
    什么是SocketSocket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP网络编程,必须理解So......
  • Linux 下Socket编程基础(转)
    1、 引言Linux的兴起可以说是Internet创造的一个奇迹。Linux作为一个完全开放其原代码的免费的自由软件,兼容了各种UNIX标准(如POSIX、UNIX System V 和 BSD UNIX ......
  • k8s集群通过nginx-ingress做tcp\udp 4层网络转发
    k8s集群可以通过nginx-ingress做tcp\udp4层网络转发1.先确认K8S集群是否开启tcp/udp[root@k8s-master-pro01tmp]#kubectlgetcm-ningress-nginxNAME......