目录
一、socket模块(套接字)
socket上应用层与TCP/IP协议通信中间的软件抽象层,帮助我们编写基于网络进行数据交互的程序,否则意味着需要自己通过代码来控制OSI七层来进行数据传输。
1.socket简介
基于文件类型的套接字(单机)
AF_UNIX
基于网络类型的套接字(联网)
AF_INET
2.代码实现
(1)服务端:
import socket
from socket import SOL_SOCKET,SO_REUSEADDR
"""
以后要养成查看源码编写代码的思路
"""
# 1 产生一个socket对象并指定采用的通信协议TCP
server = socket.socket() # 括号内不写参数,默认TCP协议 ,family = AF_INET基于网络的套接字, type = SOCK_STREAM流式协议即
# 2 绑定一个固定的地址(服务端必备的条件)
server.bind(('127.0.0.1', 8080)) # 127.0.0.1为本地回环地址,只有自己的电脑可以访问
# 3 设立半连接池(预防洪水攻击)
server.listen(5)
# 4 等待客人连接,如果没有客人则程序会停在这里
sock, addr = server.accept() # accept方法返回sock, addr
print(sock, addr) # sock就是双向通道,addr就是客户端地址
# 5 服务客人
data = sock.recv(1024) # 接收客户端发送过来的消息,1024字节
print(data.decode('utf8'))
sock.send('你好好哈哈哈哈'.encode('utf8')) # 给客户端发消息,消息必须是bytes类型
# 6 关闭双向通道
sock.close() # 四次挥手
# 7 关闭服务器
server.close() # 关闭服务器
(2)客户端
"只要想用网络通信就要使用socket模块"
import socket
# 1 产生一个socket对象并指定采用的通信协议TCP
client = socket.socket()
# 2 通过服务端的地址连接服务端
client.connect(('127.0.0.1', 8080)) # 参数是元组,ip地址是服务端的地址
# 3 直接给服务端发送消息
client.send('吃了没'.encode('utf8'))
# 4 接收服务端发送过来到的消息
data = client.recv(1024)
print(data.decode('utf8'))
# 5 断开与服务端的连接
client.close()
3.代码优化
(1)服务端
"代码优化"
import socket
from socket import SOL_SOCKET, SO_REUSEADDR
# 1 产生一个socket对象并指定采用的通信协议TCP
server = socket.socket() # 括号内不写参数,默认TCP协议 ,family = AF_INET基于网络的套接字, type = SOCK_STREAM流式协议即
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
server.bind(('127.0.0.1', 8080)) # 127.0.0.1为本地回环地址,只有自己的电脑可以访问
server.listen(5)
while True: # 添加循环,保证可以多客户端申请访问,在连接一个客户端的同时,其他客户端可以在半连接池中等待
sock, addr = server.accept() # accept方法返回sock, addr
while True: # 添加循环,可以循环接收客户端发送的消息
try: # 添加异常处理2 windows系统: 当当前客户端不发消息了,就重新接收别的客人的消息,防止win系统报错
data = sock.recv(1024) # 接收客户端发送过来的消息,1024字节
if len(data) == 0: # 异常处理1 macos系统:当客户端发送空消息,则重新接收下一条消息
break
print(f'来自客户端{addr}的字节>>>', data.decode('utf8'))
msg = input('消息发送:').strip()
sock.send(msg.encode('utf8')) # 给客户端发消息,消息必须是bytes类型
except BlockingIOError: # 异常处理
break
(2)客户端
client = socket.socket()
client.connect(('127.0.0.1', 8080))
while True: # 添加循环:可以多次发消息
msg = input('发送给服务端>>>:').strip()
if len(msg) == 0:
print('不能发空消息')
continue
client.send(msg.encode('utf8'))
data = client.recv(1024)
print('来自客户端的消息>>>', data.decode('utf8'))
优化内容:
1.聊天内容自定义:
采用input语句来获取消息,可以自定义消息
2.重复发送消息:
添加循环,将聊天的部分用循环包起来
3.用户发送消息不能为空:
本质其实是两边不能都是recv或者send,一定是一方收一方发
4.服务端多次重启可能报错:macos系统
Address already in use
解决方式1:改端口号
解决方式2:博客里面代码拷贝即可
5.当客户端异常断开的情况下 如何让服务端继续服务其他客人
windows服务端会直接报错
mac服务端会有一段时间反复接收空消息延迟报错
异常处理、空消息判断
标签:socket,sock,server,模块,data,服务端,客户端
From: https://www.cnblogs.com/DuoDuosg/p/16896606.html