东营网站设计制作百度标注平台怎么加入

当前位置: 首页 > news >正文

东营网站设计制作,百度标注平台怎么加入,企业建设网站能否报销,专业苏州房产网站建设基于tcp的套接字 文章目录 基于tcp的套接字一、套接字的工作流程二、基于tcp的套接字通信三、基于udp的套接字通信四、粘包现象 一、套接字的工作流程 Socket是应用层与TCP/IP协议族通信的中间软件抽象层#xff0c;它是一组接口。在设计模式中#xff0c;Socket其实就是一个…基于tcp的套接字 文章目录 基于tcp的套接字一、套接字的工作流程二、基于tcp的套接字通信三、基于udp的套接字通信四、粘包现象 一、套接字的工作流程 Socket是应用层与TCP/IP协议族通信的中间软件抽象层它是一组接口。在设计模式中Socket其实就是一个门面模式它把复杂的TCP/IP协议族隐藏在Socket接口后面对用户来说一组简单的接口就是全部让Socket去组织数据以符合指定的协议。 所以我们无需深入理解tcp/udp协议socket已经为我们封装好了我们只需要遵循socket的规定去编程写出的程序自然就是遵循tcp/udp标准的。 服务器端先初始化Socket然后与端口绑定(bind)对端口进行监听(listen)调用accept阻塞等待客户端连接。在这时如果有个客户端初始化一个Socket然后连接服务器(connect)如果连接成功这时客户端与服务器端的连接就建立了。客户端发送数据请求服务器端接收请求并处理请求然后把回应数据发送给客户端客户端读取数据最后关闭连接一次交互结束。 二、基于tcp的套接字通信 基于上面的套接字工作原理我们可以用python编写处如下的一段代码 #服务端 import socket#socket.AF_INET表示套接字socket.SOCK_STREAM表示tcptcp也称为流式协议 #创建套接字对象 phonesocket.socket(socket.AF_INET,socket.SOCK_STREAM) #绑定服务端ip和端口 phone.bind((127.0.0.1,8081))#开始监听listen表示半连接池限制的是请求数 phone.listen(5)# 连接循环服务端需要一直开启等待客户端的连接(连接循环) while True: #收到客户端的请求通过三次握手与四次挥手建立通信通道#conn是建立的通信通道client_addr是客户端的信息#当没有建立链接请求时服务端会一直停在phone.accept()处conn,client_addrphone.accept()#通信通道建立完成与客户端持续通信(通信循环)while True: try:print(服务端正在收数据…)#为了降低内存的压力需要限制每次接收的字节数#当没有接收到客户端的消息时服务端会一直停在conn.recv(1024)处dataconn.recv(1024) #linux中客户端中断后服务端会接收空字符此时需要跳出通信循环if len(data) 0:break print(来自客户端的数据,data)#回复客户端的信息conn.send(data.upper())#windows中客户端连接中断会报错需要用try推出通信循环except ConnectionResetError:break#关闭通信通道服务端准备与下一个客户端建立通信链接conn.close()#关闭套接字对象 phone.close() #客户端 import socketphonesocket.socket(socket.AF_INET,socket.SOCK_STREAM) #客户端不需要绑定ip和端口只需向服务端的ip和端口发送请求 phone.connect((127.0.0.1,8080)) # 指定服务端ip和端口#通信循环 while True: msginput(: ).strip()#套接字中无法发送空字符if len(msg) 0:continuephone.send(msg.encode(utf-8))dataphone.recv(1024)print(data)phone.close()如果在重启服务端的过程中出现如下的情况表示服务端仍在四次挥手的time_wait状态(服务端进程依然在后台运行)此时可以采取两种方法。 修改绑定给服务端的端口号在绑定服务端的ip和端口前加上phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) 三、基于udp的套接字通信 基于udp协议编写的套接字如下 #服务端 import socket#socket.SOCK_DGRAM表示udp协议udp是数据报协议 serversocket.socket(socket.AF_INET,socket.SOCK_DGRAM) server.bind((127.0.0.1,8080))#udp协议不需要建立通信通道因此它是不可靠的通信协议 #简单来说tcp是一对一的收发消息一个客户端结束才会回应其他客户端 #udp是一对多的收发消息由客户端发送消息时服务端就会回应 while True:#接收客户端的消息data,client_addrserver.recvfrom(1024)print(,data,client_addr)#发送消息给客户端由于没有链接通道发送信息需要带上客户端的ip和端口信息server.sendto(data.upper(),client_addr)server.close()#客户端 import socketclientsocket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True:msginput(: ).strip()#向服务端的ip和端口发送信息client.sendto(msg.encode(utf-8),(127.0.0.1,8080))data,server_addrclient.recvfrom(1024)print(data)client.close()四、粘包现象 将服务端的代码作如下的修改 import socket,subprocessphonesocket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind((127.0.0.1,8080))phone.listen(5)while True:conn,client_addrphone.accept()while True:try:dataconn.recv(1024)if len(data) 0: breakasubprocess.Popen(data.decode(utf-8),shellTrue,stdoutsubprocess.PIPE,stderrsubprocess.PIPE)resa.stdout.read()conn.send(res)except ConnectionResetError:breakconn.close() phone.close()我们尝试在客户端通过指令tasklist查看服务端的进程列表第一次客户端向服务端发送tasklist命令返回如下的结果 映像名称 PID 会话名 会话# 内存使用 System Idle Process 0 Services 0 8 K System 4 Services 0 12 K Registry 296 Services 0 26,600 K smss.exe 892 Services 0 528 K csrss.exe 1124 Services 0 2,840 K wininit.exe 1236 Services 0 3,400 K services.exe 1308 Services 0 8,912 K lsass.exe 1332 Services 0 20,172 K svchost.exe 1460 Services 0 29,432 K fontdrvhost.exe 1484 Services 0 104 K WUDFHost.exe 1536 Services 0 2,952 K svchost. 第二次当客户端向服务端发送ping www.baidu.com时会发现返回的结果依然是客户端的进程列表 exe 1596 Services 0 15,092 K svchost.exe 1640 Services 0 6,416 K WUDFHost.exe 1764 Services 0 21,224 K svchost.exe 1876 Services 0 3,868 K svchost.exe 1884 Services 0 7,436 K svchost.exe 1904 Services 0 4,420 K svchost.exe 1940 Services 0 9,876 K svchost.exe 1948 Services 0 7,880 K svchost.exe 2036 Services 0 7,128 K svchost.exe 1304 Services 0 15,372 K svchost.exe 2128 Services 0 4,932 K svchost.exe 2140 Services 0 6,348 K svchost.exe 2148 Services 0 7,032 K svchost.exe 这是怎么回事呢我们知道tcp协议是流式协议也就是说基于tcp协议发送消息时服务端套接字会把需要发送的消息给自己的操作系统而自己的操作系统将这些消息一段一段发送给客户端的操作系统由于是一段一段的发送客户端无法判断一条消息的始末所以客户端套接字每次只从操作系统中取字节数限制字节的消息当发送的消息量过大时只有一部分消息会被接收并打印到终端上剩余的消息依然在客户端的操作系统中。当我们再次向服务端发送消息接收消息以后套接字会先接收上次没有接受完的消息再接受新的消息这就产生了粘包现象。 另外如果tcp多次短间隔的发送消息发送端的套接字会将这些消息并再一起发送这样会发送接受方的另一种粘包问题。 这时候肯定有人要说如果我们不限制套接字每次接受的字节数是不是就能解决这个问题呢问题是如果我们接受的是一个很大的内容比如50g套接字会将接受的消息全部读入内存这就会引发内存爆满的情况显然这种解决方式是不可取的。 udp协议是数据报式的协议也就是说udp每次收发消息都是以一个数据报为单位的(套接字会给每次的消息加上消息头)每次接受消息都会一次取完。如果服务端接收的字节限制比接收内容小时多出来的内容会丢失(windows中会报错)而不会发送粘包的问题。由于udp的消息都含有消息头所以即便是短时间内发送多次消息也不会发生上面说到的第二种粘包问题。 tcp是基于数据流的于是收发的消息不能为空这就需要在客户端和服务端都添加空消息的处理机制防止程序卡住而udp是基于数据报的即便是你输入的是空内容直接回车那也不是空消息udp协议会帮你封装上消息头。