1 服务端套接字函数 2 s.bind() 绑定(主机,端口号)到套接字 3 s.listen() 开始TCP监听 4 s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来 5 6 客户端套接字函数 7 s.connect() 主动初始化TCP服务器连接 8 s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 9 10 公共用途的套接字函数 11 s.recv() 接收TCP数据 12 s.send() 发送TCP数据 13 s.sendall() 发送TCP数据 14 s.recvfrom() 接收UDP数据 15 s.sendto() 发送UDP数据 16 s.getpeername() 连接到当前套接字的远端的地址 17 s.getsockname() 当前套接字的地址 18 s.getsockopt() 返回指定套接字的参数 19 s.setsockopt() 设置指定套接字的参数 20 s.close() 关闭套接字 21 22 面向锁的套接字方法 23 s.setblocking() 设置套接字的阻塞与非阻塞模式 24 s.settimeout() 设置阻塞套接字操作的超时时间 25 s.gettimeout() 得到阻塞套接字操作的超时时间 26 27 面向文件的套接字的函数 28 s.fileno() 套接字的文件描述符 29 s.makefile() 创建一个与该套接字相关的文件
socket的更多用法介绍
验证客户端连接的合法性
端口的范围:0-65535
1 #server 2 import os 3 import socket 4 import hmac 5 def auth(conn): 6 msg = os.urandom(32) #生成一个随机字符串 7 conn.send(msg) #发送到client端 8 result = hmac.new(secret_key, msg) #处理这个字符串,得到一个结果 9 client_digest = conn.recv(1024) #接收client端处理的结果 10 if result.hexdigest() == client_digest.decode(‘utf-8‘): 11 print(‘合法的连接‘) #对比成功可以继续通信 12 return True 13 else: 14 print(‘不合法的连接‘) #不成功 close 15 return False 16 secret_key = b‘wangwang‘ 17 sk = socket.socket() 18 sk.bind((‘127.0.0.1‘, 8520)) 19 sk.listen() 20 conn, addr = sk.accept() 21 if auth(conn): 22 print(conn.recv(1024)) #可以正常与client端进行通信了 23 conn.close() 24 else: 25 conn.close() 26 sk.close() 27 28 #client 29 import hmac 30 import socket 31 def auth(sk): 32 msg = sk.recv(32) 33 result = hmac.new(key, msg) 34 res = result.hexdigest() 35 sk.send(res.encode(‘utf-8‘)) 36 key =b‘wangwang‘ 37 sk = socket.socket() 38 sk.connect((‘127.0.0.1‘, 8520)) 39 auth(sk) 40 sk.send(b‘upload‘) #正常的和server端进行通信 41 sk.close()
验证
主要用于内部的验证,对登陆者进行简单的验证
socketserver 模块
TCP协议下,server端可以与多个client端连接
1 #server端 2 import socketserver 3 #tcp协议的server端不需要导入socket 4 class Myserver(socketserver.BaseRequestHandler): 5 def handle(self): 6 conn = self.request 7 while True: 8 msg = input(‘>>>‘) 9 conn.send(msg.encode(‘utf-8‘)) 10 re_msg = conn.recv(1024) 11 print(re_msg.decode(‘utf-8‘)) 12 13 socketserver.TCPServer.allow_reuse_address = True 14 # 设置allow_reuse_address允许服务器重用地址 15 server = socketserver.ThreadingTCPServer((‘127.0.0.1‘, 8520),Myserver) 16 # 创建一个server, 将服务地址绑定到127.0.0.1:8520 17 server.serve_forever() 18 # 让server永远运行下去,除非强制停止程序 19 20 #client 21 import socket 22 sk = socket.socket() 23 sk.connect((‘127.0.0.1‘, 8520)) 24 while True: 25 ret = sk.recv(1024) 26 print(ret.decode(‘utf-8‘)) 27 msg = input(‘>>>‘) 28 sk.send(msg.encode(‘utf-8‘)) 29 if msg == ‘q‘: 30 break 31 sk.close()
sockterserver
########################################################
基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环
socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题)
server类:
request类:
继承关系:
以下述代码为例,分析socketserver源码:
ftpserver=socketserver.ThreadingTCPServer((‘127.0.0.1‘,8080),FtpServer)ftpserver.serve_forever()
查找属性的顺序:ThreadingTCPServer->ThreadingMixIn->TCPServer->BaseServer
- 实例化得到ftpserver,先找类ThreadingTCPServer的__init__,在TCPServer中找到,进而执行server_bind,server_active
- 找ftpserver下的serve_forever,在BaseServer中找到,进而执行self._handle_request_noblock(),该方法同样是在BaseServer中
- 执行self._handle_request_noblock()进而执行request, client_address = self.get_request()(就是TCPServer中的self.socket.accept()),然后执行self.process_request(request, client_address)
- 在ThreadingMixIn中找到process_request,开启多线程应对并发,进而执行process_request_thread,执行self.finish_request(request, client_address)
- 上述四部分完成了链接循环,本部分开始进入处理通讯部分,在BaseServer中找到finish_request,触发我们自己定义的类的实例化,去找__init__方法,而我们自己定义的类没有该方法,则去它的父类也就是BaseRequestHandler中找....
源码分析总结:
基于tcp的socketserver我们自己定义的类中的
- self.server即套接字对象
- self.request即一个链接
- self.client_address即客户端地址
基于udp的socketserver我们自己定义的类中的
- self.request是一个元组(第一个元素是客户端发来的数据,第二部分是服务端的udp套接字对象),如(b‘adsf‘, <socket.socket fd=200, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=(‘127.0.0.1‘, 8080)>)
- self.client_address即客户端地址
原文地址:https://www.cnblogs.com/zhigu/p/9663489.html
时间: 2024-10-19 20:23:35