32 socket发送大文件 UDP协议 SocketServer模块 并发编程

socket发送大文件示例

# 客户端
import struct
import json
import socket
import os

client = socket.socket()
client.connect(('127.0.0.1', 8080))

file_size = os.path.getsize(r'/Users/jiboyuan/PycharmProjects/aboutsocket/10 解决粘包问题终极版.mp4')
file_path = r'/Users/jiboyuan/PycharmProjects/aboutsocket/10 解决粘包问题终极版.mp4'
data_dic = {
    'file_name': '**上线啦.mp4',
    'file_size': file_size
}
header_json = json.dumps(data_dic)
header_bytes = header_json.encode('utf-8')
# 制作字典的报头
header = struct.pack('i', len(header_bytes))
# 发送报头
client.send(header)
# 发字典数据
client.send(header_bytes)
# 打开文件发送文件数据
with open(file_path,'rb') as f:
    for line in f:
        client.send(line)

# 服务端
import socket
import json
import struct

server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)

while True:
    conn, addr = server.accept()
    while True:
        try:
            header = conn.recv(4)
            if len(header) == 0:break
            dic_len = struct.unpack('i', header)[0]

            real_dic = json.loads(conn.recv(dic_len).decode('utf-8'))
            print(real_dic)
            file_name = real_dic.get('file_name')
            file_size = real_dic.get('file_size')
            recv_size = 0
            with open(file_name, 'wb') as f:
                while recv_size < file_size:
                    recv_data = conn.recv(1024)
                    f.write(recv_data)
                    recv_size += len(recv_data)
        except ConnectionResetError:
            break

UDP协议

UDP又叫数据报协议,意味着发消息都带有数据报头
  udp的server不需要就行监听也不需要建立连接
  在启动服务之后只能被动的等待客户端发送消息过来,客户端发送消息的时候,要带上服务端的地址
  服务端在回复消息的时候,也需要带上客户端的地址

udp协议特点:

1.客户端可以发空
2.不存在粘包问题
3.服务端不存在,也不影响客户端朝服务端发送数据
4.可以实现并发的效果

# 服务端
import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))

msg, addr = server.recvfrom(1024)
print(msg.decode('utf-8'))
server.sendto(b'hello', addr)

server.close()

#客户端
import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)

client.sendto(b'hello server baby!', server_addr)
msg, addr = client.recvfrom(1024)
print(msg, addr)

  udp特点 >>> 无链接,类似于发短信,发了就行对方爱回不回,没有任何关系
  将服务端关了,客户端起起来照样能够发数据。因为不需要考虑服务端能不能收到

# 验证udp协议有无粘包问题
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
print(server.recvfrom(1024))
print(server.recvfrom(1024))
print(server.recvfrom(1024))

import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1',8080)
client.sendto(b'hello',server_addr)
client.sendto(b'hello',server_addr)
client.sendto(b'hello',server_addr)

基于UDP实现简易版本的qq

# 服务端
import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))
while True:
    msg, addr = server.recvfrom(1024)
    print(addr)
    print(msg.decode('utf-8'))
    info = input('>>>:').encode('utf-8')
    server.sendto(info, addr)

server.close()

# 多个客户端
import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)

while True:
    info = input('>>>:')
    info = ('来自客户端1的消息:%s'%info).encode('utf-8')  # 改中文备注即可
    client.sendto(info, server_addr)
    msg, addr = client.recvfrom(1024)
    print(msg.decode('utf-8'), addr)

client.close()

小知识点补充:

  windows电脑和max电脑的时间同步功能,其实就是基于udp朝windows,max服务器发送请求获取标准时间

总结:

  TCP协议就类似于打电话

  UDP协议就类似于发短信

SocketServer模块介绍(让tcp也能支持并发)

1.能够实现并发效果
    并发:看起来像同时运行就能称之为并发
 
 2.udp在使用的时候,多个客户端要有一些io操作
    不然容易卡死

# TCP socketserver使用
import socketserver
class MyTcpServer(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            try:
                data = self.request.recv(1024)  # 对于tcp,self.request相当于conn对象
                if len(data) == 0:break
                print(data)
                self.request.send(data.upper())
            except ConnectionResetError:
                break
if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8081),MyTcpServer)
    server.serve_forever()

# UDP socketserver使用
import socketserver


class MyUdpServer(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            data, sock = self.request
            print(data)
            sock.sendto(data.upper(), self.client_address)


if __name__ == '__main__':
    server = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyUdpServer)
    server.serve_forever()

 

并发编程

操作系统的发展史

输入输出设备>>>:IO操作即(input和output)

  • 手工操作穿孔卡片

      ↓

  • 批处理(磁带)

      ↓

  • 脱机批处理系统 

 >>> 提高计算机CPU利用率的问题(问题:串行时并没有空间上的复用)

串行:一个程序完完整整的运行完毕,才能运行下一个程序

并发:看上去像同时运行

为解决cpu在执行程序,遇到io时,处于“忙等”状态:多道技术产生

多道技术:

  - 空间上的复用(多个程序共一套硬件设备,它是多道技术实现时间上的复用的基础,
   不然还要去硬盘读数据)
   
  - 时间上的复用(单个cpu的电脑上,起多个应用程序。cpu快速切换,给人的感觉是同时运行)
  
  cpu两种情况下才会切换:(先保存当前程序的运行状态)
  - 一个任务占用cpu时间过长或被操作系统强行剥夺走cpu的执行权限(比起串行效率反而降低)
  - 一个任务执行过程中遇到io操作,也会被操作系统强行剥夺走cpu的执行权限(比起串行效率提高)

并发:看上去像同时进行的
并行:同时运行
补充:单核的计算机不可能实现并行!

猜你喜欢

转载自www.cnblogs.com/zhouyongv5/p/10816318.html