客户端服务端循环收发消息,socket收发消息原理刨析,服务端循环链接请求来收发消息,如何排除端口和链接的异常

# 服务端
from socket import *

ip_port = ('127.0.0.1', 8000)
back_log = 10
buffer_size = 1024

tcp_server = socket(AF_INET, SOCK_STREAM)

tcp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # 当出现OSError: [Errno 48] Addres already in use异常时(服务端仍处于四次挥手的time_wait状态),加入这一条socket配置,重用ip和端口,得在bind前加

tcp_server.bind(ip_port)

tcp_server.listen(back_log)

while True:
   '''服务端循环链接请求来收发消息'''
   print('服务端开始运行了---')
   conn, addr = tcp_server.accept() # 服务端阻塞,等待客户端链接
   print('双向链接是', conn)
   print('客户端地址是', addr)

   while True:
      '''循环收消息和发消息,加入if判断跳出循环断开链接'''
      try:
         data = conn.recv(buffer_size) # 1024为字节,不加try当有一方链接自动断开时,会报错ConnectionResetError,所以加上try;如果不加try有些系统不会报错,data一直为空,此时加入一个if判断然后跳出循环就好了;
         print('客户端发送的消息是', data.decode('utf-8'))

         conn.send(data.upper()) # 如果输入是中文,upper()不会报错,而是将原来信息全部返回
      except Exception:
         break

   conn.close()

tcp_server.close()
# 客户端
from socket import *

ip_port = ('127.0.0.1', 8000)
buffer_size = 1024

tcp_client = socket(AF_INET, SOCK_STREAM)

tcp_client.connect(ip_port)

while True:
   '''循环发消息和收消息,加入if判断输入是否为空,是为空则再次输入'''
   msg = input('请输入:').strip()
   if not msg: continue # 判断用户输入为空的状态,如果为空进入下一次循环
   tcp_client.send(msg.encode('utf-8'))

   data = tcp_client.recv(buffer_size)
   print('服务端发送的消息是', data.decode('utf-8'))

tcp_client.close()
# 客户端1,代码一样,测试多个链接请求
from socket import *

ip_port = ('127.0.0.1', 8000)
buffer_size = 1024

tcp_client = socket(AF_INET, SOCK_STREAM)

tcp_client.connect(ip_port)

while True:
   '''循环发消息和收消息,加入if判断输入是否为空,是为空则再次输入'''
   msg = input('请输入:').strip()
   if not msg: continue # 判断用户输入为空的状态,如果为空进入下一次循环
   tcp_client.send(msg.encode('utf-8'))

   data = tcp_client.recv(buffer_size)
   print('服务端发送的消息是', data.decode('utf-8'))

tcp_client.close()
'''
socket收发消息原理刨析:
计算机分为应用软件和OS(操作系统)及硬件组成;内存有用户态内存(应用程序)和内核态内存(缓存,系统数据),客户端与服务端的交流可以这样形容:
socket应用程序把数据send()到内核态内存,然后经由网卡进行传输,另一端的内核态内存收到网卡传输的数据,然后由recv(1024)进行对数据读取;当send()数据为空时,根本没有消息传输 比如此程序用户端输入为空,就是直接按enter键,然后两端都被阻塞,recv()没有从内核态内存读取到消息 缓冲区(内核态内存)数据为队列列型,即先进先出;堆栈类型是先进后出
'''


while True: print('studying...')
原文地址:https://www.cnblogs.com/xuewei95/p/14784923.html