基于UDP的socket

面向无连接的不可靠数据传输,可以没有服务器端,只不过没有服务器端,发送的数据会被直接丢弃,并不能到达服务器端

1 #客户端
2 import socket
3 ip_port=('127.0.0.1',8080)
4 BUFSIZE=1024
5 sock_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)    #SOCK_DGRAM就是UDP
6 while True:
7     msg=input('>>').strip()
8     if not msg:continue
9     sock_client.sendto(msg.encode('utf-8'),ip_port)    #UDP用的是sendto发送数据

UDP服务端+客户端

 1 #服务端
 2 import socket
 3 ip_port=('127.0.0.1',8080)
 4 BUFSIZE=1024
 5 sock_server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
 6 sock_server.bind(ip_port)
 7 #对比TCP,缺少listen侦听地址,缺少accept等待连接的代码
 8 while True:
 9     msg,addr=sock_server.recvfrom(BUFSIZE)    #UDP接收数据使用recvfrom接收
10     print('recv:',msg,addr)
11     sock_server.sendto(msg.upper(),addr)
12 
13 #客户端
14 import socket
15 ip_port=('127.0.0.1',8080)
16 BUFSIZE=1024
17 sock_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
18 while True:
19     msg=input('>>').strip()
20     if not msg:continue
21     sock_client.sendto(msg.encode('utf-8'),ip_port)
22     # back_msg,addr=sock_client.recvfrom(BUFSIZE)    #一般UDP用于广播,不会接收数据,如果没有服务端,启用该行代码会出错
23     # print(back_msg.decode('utf-8'),addr)

由于UDP是面向无连接的(实际上有链接,不然通过什么去传数据去取数据),可以使用多个客户端连接服务端,但这并不是并发访问。

注意:

1. 发消息,都是将数据发送到己端的发送缓冲中,收消息都是从己端的缓冲区中收

   tcp:send发消息,recv收消息

   udp:sendto发消息,recvfrom收消息

2. tcp是基于数据流的,而udp是基于数据报的:

  send(bytes_data):发送数据流,数据流bytes_data若为空,自己这段的缓冲区也为空,操作系统不会控制tcp协议发空包

  sendinto(bytes_data,ip_port):发送数据报,bytes_data为空,还有ip_port,所有即便是发送空的bytes_data,数据报其实也不是空的,自己这端的缓冲区收到内容,操作系统就会控制udp协议发包。

3.1 tcp协议

(1)如果收消息缓冲区里的数据为空,那么recv就会阻塞(阻塞很简单,就是一直在等着收)

(2)只不过tcp协议的客户端send一个空数据就是真的空数据,客户端即使有无穷个send空,也跟没有一个样。

(3)tcp基于链接通信

  • 基于链接,则需要listen(backlog),指定半连接池的大小
  • 基于链接,必须先运行的服务端,然后客户端发起链接请求
  • 对于mac系统:如果一端断开了链接,那另外一端的链接也跟着完蛋recv将不会阻塞,收到的是空(解决方法是:服务端在收消息后加上if判断,空消息就break掉通信循环)
  • 对于windows/linux系统:如果一端断开了链接,那另外一端的链接也跟着完蛋recv将不会阻塞,收到的是空(解决方法是:服务端通信循环内加异常处理,捕捉到异常后就break掉通讯循环)

3.2 udp协议

(1)如果如果收消息缓冲区里的数据为“空”,recvfrom也会阻塞

(2)只不过udp协议的客户端sendinto一个空数据并不是真的空数据(包含:空数据+地址信息,得到的报仍然不会为空),所以客户端只要有一个sendinto(不管是否发送空数据,都不是真的空数据),服务端就可以recvfrom到数据。

(3)udp无链接

  • 无链接,因而无需listen(backlog),更加没有什么连接池之说了
  • 无链接,udp的sendinto不用管是否有一个正在运行的服务端,可以己端一个劲的发消息,只不过数据丢失
  • recvfrom收的数据小于sendinto发送的数据时,在mac和linux系统上数据直接丢失,在windows系统上发送的比接收的大直接报错
  • 只有sendinto发送数据没有recvfrom收数据,数据丢失

 

粘包

对昨天ssh的客户端代码做点手脚

 1 import socket
 2 import subprocess
 3 ssh_server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)   #生成socket实例对象
 4 ssh_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #重用地址,防止占用
 5 ssh_server.bind(('127.0.0.1',8080))
 6 ssh_server.listen(5)
 7 print('server run...')
 8 while True:
 9     conn,client_addr=ssh_server.accept()  #循环等待连接
10     print('客户端: ',client_addr)
11     while True: #通讯循环
12         try:
13             cmd=conn.recv(1024) #收消息
14             res=subprocess.Popen(cmd.decode('utf-8'),       #执行命令
15                              shell=True,
16                              stdout=subprocess.PIPE,
17                              stderr=subprocess.PIPE)
18             stdout=res.stdout.read()    #标准输出
19             stderr=res.stderr.read()    #标准输入
20             std=stdout+stderr
21             conn.sendall(std)
22 
23         except Exception:
24             break
25     conn.close()    #断连接,进入下一次连接等待
26 ssh_server.close() #关闭程序
服务端不动代码

相关文章:

  • 2021-10-03
  • 2021-12-19
  • 2021-05-18
  • 2022-01-20
  • 2021-04-02
  • 2021-11-30
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-12-10
  • 2022-12-23
  • 2021-06-23
  • 2021-10-15
  • 2021-10-13
相关资源
相似解决方案