内容大纲:
一、socket()里的四个参数
二、socket模块里的其他方法
三、客户端合法性验证
四、socketserver模块
一、socket()里的四个参数
sk = socket(family = AF_INET,type = SOCK_STREAM,proto = 0,fileno = None)
二、socket模块的其他方法
1、服务端套接字函数
s.bind():绑定(主机,端口号)到套接字
s.listen():开始TCP监听
s.accept():被动接受TCP客户的连接,(阻塞式)等待连接的到来
2、客户端套接字函数
s.connect():主动初始化TCP服务器连接
s.connect_ex():connect()函数的扩展版本,出错时返回错误码,而不是抛出异常
3、公共用途的套接字函数
s.recv():接收TCP数据
s.send():发送TCP数据,返回发送的字节大小,执行一次这个函数时,并不一定能发送完给定的数据,可能需要重复多次才能发送完成
s.sendall():发送完整的TCP数据,成功返回None,失败则抛出异常
s.recvfrom():接收UDP数据
s.sendto():发送UDP数据
s.getpeername():连接到当前套接字的远端的地址
s.getsockname():当前套接字的地址
s.getsockopt():返回指定套接字的参数
s.setsockopt():设置指定套接字的参数,遇到Error:Address already in use时在前面加上s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.close():关闭套接字
4、面向锁的套接字方法
s.setblocking():设置套接字的阻塞与非阻塞模式
阻塞:正在运行的进程提出系统服务请求,但是因为某种原因未得到操作系统的立即相应,该进程只能调用阻塞原语把自己阻塞住,等待相应的事件出现后才被唤醒
s.settimeout():设置阻塞套接字操作的超时时间
s.gettimeout():得到阻塞套接字的超时时间
5、面向文件的套接字函数
s.fileno():套接字的文字描述符
s.makefile():创建一个与该套接字相关的文件
三、验证客户端的合法性
背景:当使用TCP协议进行通信且不需要登录验证的时候,会有非法客户进行访问,这时可以设置客户端的合法性验证
步骤:
① server端使用os模块的urandom(n),生成一个n位的bytes类型的随机字符串
② 将该随机字符串发送给client
③ client接收随机字符串并对该字符串进行加盐的摘要,得到一个结果发送给server
④ server对随机字符用同样的盐进行摘要,并和client发送的结果进行比较
⑤ 如果结果相同就可以继续访问,结果不同就关闭conn
import os import hmac import socket key = b'hello' # 盐 def auth(conn): msg = os.urandom(32) # 随机生成一个32位的bytes类型的字符串 conn.send(msg) # 将随机字符串发送给client dig = hmac.new(key,msg) # server对随机字符串进行摘要,得到一个对象,需要用hexdigest()才能取值 result = conn.recv(1024) # 收到客户端的验证结果 if dig.hexdigest()== result.decode('utf-8'): print('合法') return True else: print('不合法') return False sk = socket.socket() sk.bind(('127.0.0.1',9005)) sk.listen() conn,addr = sk.accept() if auth(conn): msg = conn.recv(1024) print(msg.decode('utf-8')) else: conn.close()
client端:
import hmac import socket key = b'hello' def auth(sk): msg = sk.recv(32) # 接收server发送的随机字符串 result = hmac.new(key,msg) sk.send(result.hexdigest().encode('utf-8')) sk = socket.socket() sk.connect(('127.0.0.1',9005)) auth(sk) sk.send(b'welcome') sk.close()
四、socketserver模块:实现TCP协议的多客户端访问
server端:
import socketserver # 用类的方式实现 class Myserver(socketserver.BaseRequestHandler):# 必须继承socketserver.BaseRequesthandler def handle(self): # 必须实现handle方法 conn = self.request print(conn) # 这里的conn就是socket里的conn msg = conn.recv(1024) print(msg.decode('utf-8')) conn.close() server = socketserver.ThreadingTCPServer(('127.0.0.1',9002),Myserver) # 实例化 server.serve_forever() # Handle one request at a time until shutdown.
client端:
# 与socket模块相同 import socket sk = socket.socket() sk.connect(('127.0.0.1',9002)) sk.send(b'hello') sk.close()