UDP套接字,socketserver模块的使用,进程理论

1.UDP套接字

注意:

  1. udp是无链接的,先启动哪一端都不会报错
    因为udp协议无连接,所以发送数据格式为client.sendto(消息内容,服务器IP与端口的元组)
    接收数据格式:data,client_addr=server.recvfrom(1024)
    data为接收到的数据,client_addr为发送者的IP与端口的元组,用以回复消息
    因为udp没有链接,所以客户端可以同时向服务端发送数据,服务端挨个处理这些数据并返回,从而实现并发,但这有很大的局限性,比如处理数据的时间比较长,那么后面的一个客户端会明显感觉到等待

  2. udp协议不会出现粘包
    UDP是面向消息的协议,每个UDP段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据,这一点和TCP是很不同的。
    所以udp协议不用自定报头部分,提高了传输效率

  3. udp协议不可靠
    发送数据是将数据从应用程序的内存中拷贝到系统内存中,通过网卡发送出去的
    tcp协议发数据是拷贝一份数据发出去,等着对方回复一个ACK才会把系统内存中的的数据删掉,如果没收到对方的ACK,那么过段时间还会继续发
    而UDP协议是直接将数据发出去,系统内存中不做保留,他只负责发,对方爱收不收,所以会出现丢包

UDP协议的小程序示例
udp服务端

#导入socket模块
import socket

#创建服务器对象,socket.SOCK_DGRAM代表遵循UDP协议
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

#绑定地址
server.bind(('127.0.0.1',8082))

#通信循环
while True:
    #接收客户端发来的消息以及客户端IP与端口
    data,client_addr=server.recvfrom(1024)
    print(data)
    #将消息转为大写回复给客户端,
    #两个参数为回复信息与客户端IP与端口
    server.sendto(data.upper(),client_addr)

server.close()

udp客户端

import socket

client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

while True:
    msg=input('>>: ').strip()
    client.sendto(msg.encode('utf-8'),('127.0.0.1',8082))
    data,server_addr=client.recvfrom(1024)
    print(data)

2.socketserver实现并发

基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环
只有通信循环结束才能建立下一次连接,就好比是开了一个饭店,一个人在外面揽客,揽到客人以后自己又要去厨房做菜,还要等客人吃完结完账才能继续出去揽下一位客人,所以实现并发的思路就是 : 让一个人专门在门口揽客,有客人后交给服务员,让他去处理,自己继续揽客,又来了客人后再交给另外一个服务员


server=socketserver.ThreadingTCPServer(参数一,参数二)
参数一为服务端绑定的IP以及端口
参数二为自定义的类来处理通信循环的
server.serve_forever() # 链接循环

  1. 自定义的类必须继承socketserver.BaseRequestHandler
  2. 自定义的类必须有handle(self)方法用来处理通信循环

基于tcp通信实现并发示例
服务端:

import socketserver

# 自定义类用来处理通信循环
class MyTCPhanler(socketserver.BaseRequestHandler):
   def handle(self):
       while True:
           try:
               data = self.request.recv(1024)
               if len(data) == 0: break  # 针对linux系统
               print('-->收到客户端的消息: ', data)
               self.request.send(data.upper())#self.request为双向连接对象,相当于之前的conn
           except ConnectionResetError:
               break

       self.request.close()


if __name__ == '__main__':
   server=socketserver.ThreadingTCPServer(('127.0.0.1',8081),MyTCPhanler)
   server.serve_forever() # 链接循环

客户端:(客户端不用变)

from socket import *
client = socket(AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1', 8081))

# 通信循环
while True:
    client.send('hello'.encode('utf-8')) 
    data=client.recv(1024)
    print(data)

client.close()

基于UDP通信实现并发示例
服务端:

import socketserver

class MyUdphandler(socketserver.BaseRequestHandler):
    def handle(self):
        data,sock=self.request
        sock.sendto(data.upper(),self.client_address)
        
if __name__ == '__main__':
    server=socketserver.ThreadingUDPServer(('127.0.0.1',8081),MyUdphandler)
    server.serve_forever()

客户端:(还是不变)

from socket import *

client=socket(AF_INET,SOCK_DGRAM)

while True:
    client.sendto(b'hello',('127.0.0.1',8081))
    data,server_addr=client.recvfrom(1024)
    print(data)

3.进程理论

进程指的是一个正在进行/运行的程序,进程是用来描述程序执行过程的虚拟概念

    进程vs程序
    程序:一堆代码
    进程:程序的执行的过程

    进程的概念起源于操作系统,进程是操作系统最核心的概念,操作系统其它所有的概念都是围绕进程来

    操作系统理论:
        1. 操作系统是什么?
            操作系统是一个协调\管理\控制计算机硬件资源与应用软件资源的一段控制程序
            有两大功能:
                1. 将复杂的硬件操作封装成简单的接口给应用程序或者用户去使用
                2. 将多个进程对硬件的竞争变得有序

    操作系统发展史
        并发: 多个任务看起来是同时运行的
        串行:一个任务完完整整地运行完毕,才能运行下一个任务

        多道技术:(复用=>共享/共用)
            1. 空间上的复用:多个任务复用内存空间
            2. 时间上的复用:多个任务复用cpu的时间
                1. 一个任务占用cpu时间过长会被操作系统强行剥夺走cpu的执行权限:比起串行执行反而会降低效率
                2. 一个任务遇到io操作也会被操作系统强行剥夺走cpu的执行权限:比起串行执行可以提升效率

你可能感兴趣的:(UDP套接字,socketserver模块的使用,进程理论)