8-13-基于tcp协议实现套接字通信-client端,sever端

上节课复习:
    1、tcp协议

今日内容:
    1、socket的通信流程介绍
    2、基于tcp协议通信的套接字程序


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

服务端使用的是: NOKIA老年机,
			使用流程:
				购买一部设置打开网络 指定数据传输为流格式的手机,
				拔掉电池插手机卡从而绑定一个手机号,
				开机,
				接听电话


客户端使用的是: Iphone概念机
			使用流程
				买来的时候,就是开机状态,只需要打开网络 和 指定数据传输为流格式,
				其里面就已经绑定了一个动态的虚拟手机号码(这个虚拟号码,经常会变动), 所以,不需要抠出电池,装手机卡
				拨号打电话
					




建桥 和 拆桥 的ACK SYN等信号 ,不是在要建立的桥上传送的(桥上传输的 只有要传输的数据)

用于确认是否收到 数据的信号,也不是在桥上传送的(相当于 收到快递后,打电话告诉对方我已收到货物;而不是 通过快递再寄过去 '我已收到货物'的一个信息)

	类似:
		双方通过收发快递,
		两端的人打电话询问 是否 收到货物
		而不是通过快递的方式 寄送 一张小纸条写着'我已收到'之类的信息




半连接池,暂存发送过来的请求.
	如果半连接池满了,则会直接拒绝请求

服务器总共可以容纳请求的数量为 (容量池)n+1
	1 表示当前正在服务的哪个请求





udp 没有listen listen是监听建立的连接
而  upd则根本就没有建立连接



SOCKET.AF_INET指定时基于网络的套接字
stream  指定为流式(表示可以分批次收)



conn是一个双向链接  用于收发


服务端必须要绑定 固定地址
客户端没必要绑定 固定地址


客户端的connect  对应  服务端的accept

recv(最大的字节接收个数)
	


发送,要指定原文件的编码,
	中间都是要转成二进制编码 byte类型
接收,要进行解码




服务端的两个循环

	1、链接 循环: 与下一个请求建立连接

			接客: 用于接通新客户
		    # 要把conn,client=phone.accept()包括在 循环中
		    # 因为 每一次都是进行依次新的通话


	2、通信 循环: 处理当前请求

			服务当前客人


这种方式:接客(一次接待一个人)  与 服务(一次服务一个人) 同一时间只能进行一样

丧失了并发的效果,不过保证了  一直工作的大前提



未引入线程时   进程只能充当一个人

	上述 就是如此,前后始终都只要一个人

引入线程后  一个线程可以充当一个人

	分出多个人,一波人干 接待  一拨人干 服务



客户端的connect  对应  服务端的accept


在编写客户端时   应该在信息即将要发送的信息都准备好,然后在建立连接并轮转为自己服务的时间段内,快速的完成数据的发送,  而千万不要都为该客户服务了, 而该客户还在磨磨唧唧的,占用宝贵的服务器资源



注意:windows系统返回的信息 的编码为:gbk 
	对返回的结果进行解码时  要选择正确的编码

规定头的长度 目的:知道 从哪里开始 到哪里结束


socketsever模块  实现并发(tcp  和 upd 都行)


rcvd:收到的东西首先是放在 缓存中的,缓存 是位于内存的, 也不可能把内存都当做缓存用

这个缓存 是可以动态增加的,但是占用的还是内存的存储空间,所以还是不能无限大

一次性发过来的数据,全部存储在这个缓存之中,通过rcvd取出来的时候,可以指定一次从这个缓存中取出多少个字节

在rcvd(字节长度)中可以指定缓存中一次能接收的数据的最大长度

	可解决 命令这一种情况的问题,因为命令的结果不会很大,
	但是如果要传的是一个文件 大小为几十个G,则内存是不够的


如果客户端发送的内容为 空: 服务端虽然接收到了这个空,但是对服务端的缓存没有任何作用,内容纹丝不动,不会有丝毫增加


私网 ip 是没有办法  往外走的
要使用公网ip


阿里云
服务端监听 0 0 0 0(阿里已做好映射关系)
客户端连的时候  连的是公网ip

============================> 01 基于tcp协议实现简单套接字通信 <===============================
client端:
				
				import socket

				# 1、买手机
				phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # SOCK_STREAM=》TCP协议


				# 2、拨电话
				phone.connect(("127.0.0.1", 8080))

				# 3、发/收消息
				phone.send("hello".encode('utf-8'))
				data = phone.recv(1024)
				print("服务的返回的数据:", data.decode('utf-8'))

				# 4、关闭
				phone.close()



sever端:
				
				import socket

				# 1、买手机
				phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # SOCK_STREAM=》TCP协议

				# 2、插手机卡
				phone.bind(("127.0.0.1", 8080))  # 本地回环

				# 3、开机
				phone.listen(5)
				print('starting %s:%s' %("127.0.0.1", 8080))

				# 4、等电话链接
				conn, client_addr = phone.accept()

				# 5、收/发消息
				data = conn.recv(1024)  # 最大接收的字节个数
				print("收到的客户端数据:", data.decode('utf-8'))
				conn.send(data.upper())

				# 6、关闭
				conn.close()  # 挂电话
				phone.close()  # 关机


=====================================> 02 加上循环 <=========================================

						注意: 老式NOKIA手机使用流程(拔掉电池,插手机卡,然后开机)

client端:
		
		1、买手机,并为买的手机指定参数:
			
			AF_INET 指定是基于网络的套接字
			SOCK_STREAM  指定为流式(表示可以分批次收,每次接收的数据大小有最大限制)

				phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # SOCK_STREAM=》TCP协议

		2、拨电话    # 客户没必要绑定一个固定的手机号
			拨号建立连接
				# 输入客服的手机号后进行拨号
				phone.connect(("127.0.0.1", 8080))

		3、发/收消息(通话中)=>通信循环
				
				一直和客服进行通话
				while True:
				    
				    # 客户咨询内容
				    msg = input(">>: ").strip()
				    
				    # 手机将咨询内容编码后进行发送
				    phone.send(msg.encode('utf-8'))
				    
				    # 手机接收客服的回复
				    data = phone.recv(1024)
				    # 将该回复 解码后进行查看
				    print("服务的返回的数据:", data.decode('utf-8'))

		4、关闭(挂电话)
				phone.close()



sever端:

				"""
				服务端应该满足的特性:
				    1、一直对外提供服务
				    2、并发地提供服务
				"""

				
		1、买手机

				# 购买一个手机,并且对手机的工作方式进行设定
				# ①指定手机是基于网络工作的
				# ②指定手机处理数据是基于流形式的(即一个大数据可以分多次接收)
				phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # SOCK_STREAM=》TCP协议


		2、插手机卡
			客服,要绑定一个手机号
				# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加	
				phone.bind(("127.0.0.1", 8080))  # 本地回环

		3、开机
				# 设置 在等待队列中的最大等待个数
				# 开机,开启监听模式(并指定可拨入电话的最大数量)
				# 实际电话中的客户个数+1  因为当前正在服务的有一个人,还有两个人在线上等待
				phone.listen(5)
				print('starting %s:%s' %("127.0.0.1", 8080))

		
		4、等电话链接(等其他人的电话拨进来)=>链接循环

        
				一直进行扫描: 如果上一次通话结束, 则从半连接池中取出一个请求,与之建立连接(服务端 到 客户端 的桥)

				
				while True:
					
				    conn,           client_addr   =  phone.accept()
				   本次通话的控制权	客户的手机号	     建立的连接
				   
				   通过本次建立的连接   得到 本次通话连接的控制权(即挂掉电话等权利) 和 客户的手机号

				    print(client_addr)
		
		5、收/发消息(通话中)=>通信循环
					
					一直与当前对客户进行交流, 如果对方不发送咨询内容,就结束本次服务
				    while True:
				        try:
				            data = conn.recv(1024)  # 最大接收的字节个数
				            
				            如果当前客户,不发送咨询内容了,就结束本次服务
				            if len(data) == 0:  # 针对linux系统
				                break
				            
				            对接收的内容,进行翻译查看
				            print("收到的客户端数据:", data.decode('utf-8'))
				            
				        	对客户的咨询,进行答复
				            conn.send(data.upper())

				        except Exception:  # 针对windows系统
				            break
		

		6、关闭(断开本次连接,即 挂掉本次通话)
				    conn.close()
		挂掉电话,并开始从后面的电话中接入一个新电话


		7、关机
				phone.close()


=======================================> 远程执行命令 <=====================================
client端:
				
				import socket

				# 1、买手机
				phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # SOCK_STREAM=》TCP协议

				# 2、拨电话
				phone.connect(("127.0.0.1", 8080))

				# 3、发/收消息=>通信循环
				while True:
				    cmd = input("[root@localhost]# ").strip()
				    phone.send(cmd.encode('utf-8'))
				    data = phone.recv(1024)
				    print(data.decode('gbk'))

				# 4、关闭
				phone.close()



sever端:
				"""
				服务端应该满足的特性:
				    1、一直对外提供服务
				    2、并发地提供服务
				"""

				import socket
				import subprocess

				# 1、买手机
				phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # SOCK_STREAM=》TCP协议

				# 2、插手机卡
				phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 就是它,在bind前加

				phone.bind(("127.0.0.1", 8080))  # 本地回环

				# 3、开机
				phone.listen(5)
				print('starting %s:%s' % ("127.0.0.1", 8080))

				# 4、等电话链接=>链接循环
				while True:
				    conn, client_addr = phone.accept()
				    print(client_addr)
				    # 5、收/发消息=>通信循环
				    while True:
				        try:
				            cmd = conn.recv(1024)  # 最大接收的字节个数
				            if len(cmd) == 0:  # 针对linux系统
				                break

				            obj = subprocess.Popen(cmd.decode('utf-8'),
				                                   shell=True,
				                                   stdout=subprocess.PIPE,
				                                   stderr=subprocess.PIPE
				                                   )

				            res=obj.stdout.read()+obj.stderr.read()  # ???
				            print(res)
				            conn.send(res)
				        except Exception:  # 针对windows系统
				            break

				    # 6、关闭
				    conn.close()  # 挂电话
				phone.close()  # 关机
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值