网络编程(三) 大文件传输与UDP通信

异常处理、UDP通信、socketserver模块

1、UDP通信基本使用

1、socket套接字的导入

import socket
server = socket.socket(type= socket.SOCK_DGRAM)
#type不写默认是TCP协议

服务端:

2、UDP没有半连接池的概念(listen),也无双向通道,无需accept,直接通信循环

3、接收数据有两个返回值:server.recvfrom(1024)

data,addr = server.recvfrom(1024)
print(data)#客户端的消息
print(addr)#客户端的地址

完整的服务端:

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

while True:
    data ,addr = server.recvfrom(1024)
    server.sendto(data.upper(),addr)

4、发数据:sendto

客户端:

无需建立连接的操作,直接进入通信循环。但是要给一个连接地址用于发送

import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_address = ('127.0.0.1'.8080)
while True:
    client.sendto(b'hello',server_address)
    data,addr = client.recvfrom(1024)

总结UDP和TCP的区别:

UDP相当于发短信;TCP相当于打电话

2、UDP与TCP的4大区别

  1. UDP客户端允许发空:udp有一个报头

  2. udp协议不会粘包:

    不会粘包

    #客户端代码
    import socket
    client = socket.socket(type=socket.SOCK_DGRAM)
    
    server_address = ('127.0.0.1',8080)
    while True:
        client.sendto(b'hello',server_address)
        client.sendto(b'hello',server_address)
        client.sendto(b'hello',server_address)
    
    #服务端代码
    import socket
    
    server = socket.socket(type=socket.SOCK_DGRAM)
    server.bind(('127.0.0.1',8080))
    # while True:
    data ,addr = server.recvfrom(1024)
    print(data)
    data ,addr2 = server.recvfrom(1024)
    print(data)
    data ,addr3 = server.recvfrom(1024)
    print(data)
    
  3. 服务端断开的情况下,客户端不会报错:

    会一直停留在客户端的”输入“那一行。但是如果继续输入,则会报错

    ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
    

3、udp支持并发:看上去是同时运行的。

#服务端
import socket

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

while True:
    data ,addr = server.recvfrom(1024)#在这里接受任何向这个地址发送消息的客户端。
    server.sendto(data.upper(),addr)

4、实现一个简易版本的QQ

客户端代码

import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_address = (('127.0.0.1',8080))
while True:
    msg = input('>>>').encode('utf-8')
    msg = '来自客户端1的信息:%s'%msg
    client.sendto(msg.encode('utf-8'),server_address)
    data,addr = client.recvfrom(1024)
    print(data.decode('utf-8'))

服务端代码

import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
while True:
    data,addr = server.recvfrom(1024)#接收往这个地址放信息的任何客户端
    print(data.decode('utf-8'))
    msg = input('>>>')
    server.sendto(msg.encode('utf-8'),addr)

5、socketserver模块

5.1 让TCP支持并发

#客户端代码
import socket

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

while True:
    client.send(b'hello')
    data = client.recv(1024)
    print(data.decode('utf-8'))
#服务端代码
import socketserver
class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        # print('来啦 老弟')
        while True:
            data = self.request.recv(1024)
            print(self.client_address)  # 客户端地址
            print(data.decode('utf-8'))
            self.request.send(data.upper())

if __name__ == '__main__':
    """只要有客户端连接该地址  会自动交给自定义类中的handle方法去处理"""
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyServer)  # 创建一个基于TCP的对象
    server.serve_forever()  # 启动该服务对象

5.2socketserver同样支持UDP

#服务端代码
import socketserver

class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        # print('来啦 老弟')
        while True:
            data,sock = self.request
            print(self.client_address)  # 客户端地址
            print(data.decode('utf-8'))
            sock.sendto(data.upper(),self.client_address)
if __name__ == '__main__':
    """只要有客户端连接  会自动交给自定义类中的handle方法去处理"""
    server = socketserver.ThreadingUDPServer(('127.0.0.1',8080),MyServer)  # 创建一个基于TCP的对象
    server.serve_forever()  # 启动该服务对象
#客户端代码
import socket

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

while True:
    client.send(b'hello')
    data = client.recv(1024)
    print(data.decode('utf-8'))

6、异常处理

当try中存在多个错误的时候,遇到第一个错误立即停止下面的代码,直接进“except”中弹出信息

try:
    name#第一个错
    l = [1,2,3]
    l[111]#第二个错
    d = {'name':'jason'}
    d['password']#第三个错
except NameError:
    print('NameError')
except IndexError:
    print('indexerror')
except KeyError:
    print('keyerror')
#运行程序的结果是NameError
Exception万能异常.以及else和finally
try:
    # name
    l = [1,2,3]
    l[111]
    # d = {'name':'jason'}
    # d['password']
except Exception:  # 万能异常  所有的异常类型都被捕获
    print('老子天下无敌')
else:
    print('被检测的代码没有任何的异常发生 才会走else')
finally:
    print('无论被检测的代码有没有异常发生 都会在代码运行完毕之后执行我')
万能异常BaseException
try:
    # name
    l = [1,2,3]
    l[111]
    d = {'name':'jason'}
    d['password']
    # Exception
except BaseException:  # 万能异常  所有的异常类型都被捕获
    print('老子天下无敌')

BaseException是所有异常的祖宗。父类。

#点开源码
Exception(BaseException)
主动抛异常raise
if 'egon' == 'DSB':
    pass
else:    
    raise TypeError('尽说大实话')# 关键字raise就是主动抛出异常
#命令行飘红(以下代码飘红)
Traceback (most recent call last):
  File "C:/untitled6/32.py", line 4, in <module>
    raise TypeError('尽说大实话')
TypeError: 尽说大实话
断言assert(判断)
l = ['a','b']
assert len(l) < 0
#与raise一样,运行结果飘红
自定义异常
class MyError(BaseException):
     def __init__(self,msg):
         super().__init__()
         self.msg=msg
     def __str__(self):
         return '<dfsdf%ssdfsdaf>' %self.msg

raise MyError('我自己定义的异常')  # 主动抛出异常其实就是将异常类的对象打印出来,会走__str__方法
原文地址:https://www.cnblogs.com/ZDQ1/p/11327940.html