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模块

这部分内容会了之后感觉就可以购买慢慢试试我的网页了。

猜你喜欢

转载自www.cnblogs.com/xiaoyaotx/p/12578728.html