Python学习第33天(socket收发消息原理、服务器循环链接)
今天看的内容有限,感觉前面没有看Linux和底层基础知识有点吃亏,不过今天已经把报告整出来了,再也不用为这个东西恼火了
一、关于socket收发消息的原理
首先关于计算机,分为三层:应用软件——操作系统(OS)——硬件(特指内存)
内存又被分为:内核区(存放操作系统,用于收发指令代替你去操作硬件,例如:网卡)
用户区:各种存放的应用程序
socket在执行recv和send的时候,其本质是想内核区发送或者接受,再由os去操作系统通过网卡进行信息的传递交互
所以这个在实际中机会又下面这个问题:
首先是客户端和服务端的代码:
#服务端 import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bind(('127.0.1.11',8000)) #注意,地址和端口是以一个元组的形式给入 phone.listen(5) print('waiting!!!') conn,addr = phone.accept() print('oking') msg = conn.recv(1024) print(msg) conn.send(msg.upper()) conn.close() phone.close() #客户端 import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.1.11',8000)) phone.send('hello'.encode('utf-8')) msg = phone.recv(1024) print(msg)
如果你在客户端发送一个空的字符串,程序运行之后会显示发送是成功的,但是服务器没有回应,客户端也是卡在原地
之所以显示发送成功就是刚才说的原理中,发送是向我们的内存os发送,不论发送什么都会成功,但是空是无法传输的,所以服务器会一直处在等待的状态
最终导致了无法继续愉快的玩耍
现实中我们在进行与服务器交互的时候往往不会一次交流就断开,所以我们可以增加循环,进行不停的交流
# 服务端 import socket # 可以将内部可能出现的参数在建立服务前进行设置,便于后期的修改 ip_port=('127.0.0.1',8080) back_log=5 buffer_size=1024 tip_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) tip_client.bind(ip_port) tip_client.listen(back_log) conn,addr = tip_client.accept() print('conn:',conn) print('addr',addr) # 具体去看看conn和addr是个啥东西 while True: msg = conn.recv(1024) print('收到的消息是:',msg) conn.send(msg.upper()) conn.close() tip_client.close() #客户端 import socket ip_port=('127.0.0.1',8080) buffer_size=1024 tip_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) tip_server.connect(ip_port) while True: msg = input('>>>').strip() tip_server.send(msg.encode('utf-8')) res = tip_server.recv(buffer_size) print('服务器返回消息',res) tip_server.close()
但是这个在多次等待反馈运行的过程中会存在这么一个问题,客户端主动强行断开会导致服务端出现如下的错误
分析一下原因:
暂时先保留这个问题,会存在另一个问题,我们在日常中,往往是多个客户端会向同一服务器发送链接请求
我们该如何处理呢?
代码进一步改进:
主要是针对服务器的:
import socket # 可以将内部可能出现的参数在建立服务前进行设置,便于后期的修改 ip_port=('127.0.0.1',8080) back_log=5 buffer_size=1024 tip_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) tip_client.bind(ip_port) tip_client.listen(back_log) while True: # 这样,当一个用户断开后,我们就可以从backlog中拿取等待中的客户 conn,addr = tip_client.accept() print('conn:',conn) print('addr',addr) # 具体去看看conn和addr是个啥东西 while True: #同时在此处增加判断机制,保证conn无效之后能及时的跳出循环,重新链接下一个客户 try: msg = conn.recv(1024) print('收到的消息是:',msg) conn.send(msg.upper()) except Exception: break #跳出同一链接内的交互,进行洗一次的链接等待 conn.close() tip_client.close()
此时,当多个客户端等待的时候,正在链接的客户端一旦断开链接,就可以自动的开始下一个链接反馈
马上又是周末了
这周末两个事情:
1.安装Linux的虚拟机
2.复习os模块和pickle模块
这部分内容会了之后感觉就可以购买慢慢试试我的网页了。