8-17 socketserver实现并发通信

本周内容:

    day01、套接字(***)
        udp
        socketserver
        阿里云

    day02:
        1、元类(***)
            单例模式
        2、猴子补丁
        3、内置函数
        4、垃圾回收机制

    day03:并发编程(******)
        进程起源操作系统

        操作系统的发展史

==================================================================================

TCP  VS  UDP协议

		1、可靠性
			tcp协议是可靠协议:
			  发送一个信息后,对方必须回复一个ack确认信息(确认收到),才会将自己这端的数据从内存中删除

			udp协议不可靠:
			  发送一条消息就会立即删除,不管对方是否接收到
			  ,所以udp应用于对可靠性要求不高的场景

		2、有无链接
			
			tcp有链接,
			
			udp无链接
				因为没有链接请求, 所以不需要监听链接, 也即没有listen
				connect是 建立连接,所以udp不需要

		3、传输数据的效率
			udp更高

		4、粘包问题

			tcp 是流式协议,把短时间内连续发送的多个信息  一起发送


			udp协议称之为数据报协议,每次发送都是一个完整的数据报,一个发送唯一对应一个接收

			发送一条信息,就是单独一条,所以udp协议根本就不会出现粘包问题

			即使发空,也是一个完整的数据报里面包含自己的ip地址,端口,目标的ip地址端口,只不过实际数据部分是一个 空




udp协议的套接字通信:

		开多个客户端与服务端进行通信,虽然看起来像是并发,
		只不过由于速度很快,仍然是一个一个客户端处理的,
		所以看起来像是并发的


		一个客户端的阻塞,会引起其他客户端的阻塞

		可以通过time.sleep()  来验证 


		upd可以先启动客户端, 暂时不启动服务端, 输入数据后直接发送, 只不过是发送出去的数据 就石沉大海了, 没有任何的主机接收到这条信息
		而tcp必须先启动服务端,再启动客户端: 因为 tcp通信需要建立链接, 服务端如果事先不在,客户端就链接不上



socketsever模块(真正实现并发的效果)

		基于 tcp协议的两个死循环

			一个建立链接     一个进行通信

		只需要改写 服务端就可以

		两者代码之间的等效:

				sever_forever()  对应 建立连接的死循环


				把  conn直接赋给 severrequest对象

		非并发情况下:
	
			tcp服务端: 店里总共就一个人, 这个人先拉客(建链接), 然后再去服务(进行通信)这个客人;
						服务完之后,再去拉客,然后再去服务这个客人 ....... 

			udp也类似


		并发情况下:
	
			把 原本(只有一个主线程)  干的服务(一次服务一个人)   开成 若干个 子线程 服务(一个子线程  服务一个链接)
			serve_forver 只有主线程一个人干这个 接待,  每接待一个人找另外一个服务员  服务这个链接 

				即专门的一个人站在店门口不停的拉客(建链接) ,为每一个客人都分配一个服务员进行服务(进行通信);  


		self.request   

			tcp中:相当于 	conn

			udp中:相当于	data  套接字对象



=====================================01 基于udp协议的套接字通信===================================
	
服务端:


			from socket import *
			import time

	SOCK_DGRAM:数据报协议

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

	注意:udp中没有建链接的请求,所以不需要listen
 		
		所以, 既然没有建链接的请求, 也自然不需要 使用accept 建立链接

		也因此,没有链接循环,直接进行通信循环即可

			while True:  # 通信循环

	不用指定跟谁收,发给谁: 因为就是基于现成的收到的数据报中的内容实现 数据收发的

				sever.recvfrom(1024) 客户端接收后,返回的内容是一个元组, 既有 ①client发过来的数据,也有 ②client端的地址

	是一个元组, 进行解压操作

			    data, client_addr = server.recvfrom(1024)
	
	加sleep(10): 用来验证udp通信的过程并不是并发的, 未加sleep时,看起来像是并发单纯只是因为 程序运行速度太快了

			    time.sleep(10)
			    server.sendto(data.upper(), client_addr)


客户端:
			
			from socket import *

			client = socket(AF_INET, SOCK_DGRAM)

	注意: 不能出现connect, 因为connect是建链接, 而udp中没有链接

	
	所以直接发,就ok

			while True:
			    msg = input('输入要发送的内容: ').strip()
			    
	直接在发送的整条信息中,需要包含: ①数据内容  ②server端地址

			    client.sendto(msg.encode("utf-8"), ('127.0.0.1', 8080))

			    data, server_addr = client.recvfrom(1024)
			    print(data.decode('utf-8'))




===============================02 基于socketserver模块实现并发tcp===============================
 
	服务端:
			
			# from socket import *
			#
			#
			# server=socket(AF_INET,SOCK_STREAM)
			# server.bind(('127.0.0.1',8080))
			# server.listen(5)
			#
			# while True:
			#     conn,addr=server.accept()
			#     print(addr)
			#
			#     while True:
			#         try:
			#             data=conn.recv(1024)
			#             if len(data) == 0:break
			#             conn.send(data.upper())
			#         except Exception:
			#             break
			#
			#     conn.close()

			# 支持并发版本
			import socketserver


# 定义一个类(类名随意), 必须继承 socketserver下面的BaseRequestHandler 这个类

			class MyRequestHandler(socketserver.BaseRequestHandler):

# 在这个类中,必须要有一个handle方法: 用于处理通信 ,就把所有干通信的活儿 交给 它来干


			    def handle(self):  # 处理通信
			        print(self.client_address)
 			        while True:
			            try:

# 这个self.request就等同于之前的conn
# self.client_address 就是客户端的地址了

他们都封装在这个对象里面了
			            
			                data = self.request.recv(1024)  # self.request=>conn
			                if len(data) == 0: break
			                self.request.send(data.upper())
			            except Exception:
			                break

	# 这个就等同于之前的 conn.close()
			        
			        self.request.close()

# 建链接
			if __name__ == '__main__':
		#指明是基于TCP  
			    s = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyRequestHandler, bind_and_activate=True)
			    s.serve_forever()


	客户端:
			
			from socket import *

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

			while True:
			    msg=input(">>: ").strip()
			    if len(msg) == 0:
			        continue

			    client.send(msg.encode('utf-8'))
			    data=client.recv(1024)
			    print(data.decode('utf-8'))




===============================03 基于socketserver模块实现并发 udp ===============================

服务端

				import socketserver


				class MyRequestHandler(socketserver.BaseRequestHandler):
				    def handle(self):  # 处理通信
				        data,server=self.request
				        server.sendto(data.upper(),self.client_address)

				if __name__ == '__main__':
				    s = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyRequestHandler, bind_and_activate=True)
				    s.serve_forever()


客户端

				from socket import *

		DGRAM:即 DATA GRAM
				
				client = socket(AF_INET, SOCK_DGRAM)

				while True:
				    msg = input('>>: ').strip()
				    client.sendto(msg.encode("utf-8"), ('127.0.0.1', 8080))

				    data, server_addr = client.recvfrom(1024)
				    print(data.decode('utf-8'))



===============================04 阿里云部署===============================

	服务端

			# coding:utf-8
			# from socket import *
			#
			#
			# server=socket(AF_INET,SOCK_STREAM)
			# server.bind(('127.0.0.1',8080))
			# server.listen(5)
			#
			# while True:
			#     conn,addr=server.accept()
			#     print(addr)
			#
			#     while True:
			#         try:
			#             data=conn.recv(1024)
			#             if len(data) == 0:break
			#             conn.send(data.upper())
			#         except Exception:
			#             break
			#
			#     conn.close()

			# 支持并发版本
			import socketserver


			class MyRequestHandler(socketserver.BaseRequestHandler):
			    def handle(self):  # 处理通信
			        print(self.client_address)
			        while True:
			            try:
			                data = self.request.recv(1024)  # self.request=>conn
			                if len(data) == 0: break
			                self.request.send(data.upper())
			            except Exception:
			                break
			        self.request.close()


			if __name__ == '__main__':
			    s = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyRequestHandler, bind_and_activate=True)
			    s.serve_forever()


	客户端

			from socket import *

			client=socket(AF_INET,SOCK_STREAM)
			client.connect(('121.199.45.113',8080))

			while True:
			    msg=input(">>: ").strip()
			    if len(msg) == 0:
			        continue

			    client.send(msg.encode('utf-8'))
			    data=client.recv(1024)
			    print(data.decode('utf-8'))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值