欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

socket实现简单的服务器端和客户端的交互

程序员文章站 2022-07-01 08:02:18
...

基于socket在本机上实现最简单的服务器端和客户端的交互,在实现过程中遇到问题:
服务器端和客户端都在运行的时候,客户端突然停止,服务器端会报错:

Traceback (most recent call last):
  File "E:/python_learn/python_cord/day29/服务器.py", line 41, in <module>
    data=conn.recv(buffer_size)#收消息
ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。

代码如下:
服务器端


#import socket
#当写import socket时,下面需要写成socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#可以用from socket import *,此时下面可以写成socket(AF_INET,SOCK_STREAM)
from socket import *
ip_port=('127.0.0.1', 8000)
back_log=5
buffer_size=1024
tcp_server=socket(AF_INET, SOCK_STREAM)
tcp_server.bind(ip_port)
tcp_server.listen(back_log)
print('服务端开始运行')
conn,addr=tcp_server.accept()#服务器端阻塞
print('双向连接是',conn)
print('客户端地址是',addr)
while True:
    print('服务器开始运行了')
    data=conn.recv(buffer_size)#收消息
    print('客户端发来的消息',data)
    conn.send(data.upper())
conn.close()#socket关闭掉
tcp_server.close()

客户端

import socket

tcp_client=socket.socket(socket.AF_INET, socket.SOCK_STREAM)

tcp_client.connect(('127.0.0.1', 8000))
while True:
    msg=input('>>:').strip()
    tcp_client.send(msg.encode('utf-8'))
    data=tcp_client.recv(1024)
    print('收到服务器端发来的消息:',data)

产生错误原因分析:
在客户端断掉之后,服务器端的本次conn异常结束,data=conn.recv(buffer_size)接收不到东西。程序抛出异常。

优化(解决办法)
虽然我们设置了接收池back_log为5,但是我们的tcp_server.accept()只有一个。意味着只能接收一次connect。接收完之后就开始跟这一次的connect进行通信,通信完成之后就关闭掉了。此时服务器端只服务一个人。但是服务器端的目的是循环服务很多人。简单来说来一个链接就能接收住。
当本次conn异常结束后,会抛出异常。我们可以用python提供的异常处理来抓住此次异常,并使用break结束此次的循环,让它可以再等待下一个客户端消息得到来。
改进后代码:

#服务器端
from socket import *
ip_port=('127.0.0.1', 8000)
back_log=5
buffer_size=1024
tcp_server=socket(AF_INET, SOCK_STREAM)
tcp_server.bind(ip_port)
tcp_server.listen(back_log)
while True:
    conn, addr = tcp_server.accept()  # 服务器端阻塞
    print('双向连接是', conn)
    print('客户端地址是', addr)
    while True:
        print('服务器开始运行了')
        try:
            data=conn.recv(buffer_size)#收消息
            print('客户端发来的消息',data)
            conn.send(data.upper())
        except Exception:
            print('=====')
            break
        data=conn.recv(buffer_size)#收消息
        print('客户端发来的消息',data)
        conn.send(data.upper())
    conn.close()#socket关闭掉
tcp_server.close()

外层循环的目的:使服务器可以为多个客户端提供服务
里层循环的目的:使服务器可以完成对同一个客户端发送的多条消息的收发工作