《Python》网络编程之验证客户端连接的合法性、socketserver模块

摘要:
如果出现错误,将引发异常。
一、socket的更多方法介绍
# 服务端套接字函数
s.bind()    # 绑定(主机,端口号)到套接字
s.listen()  # 开始TCP监听
s.accept()  # 被动接受TCP客户的连接,(阻塞式)等待连接的到来

# 客户端套接字函数
s.connect()     # 主动初始化TCP服务器连接
s.connect_ex()  # connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

# 公共用途的套接字函数
s.recv()         # 接收TCP数据
s.send()         # 发送TCP数据
s.sendall()      # 发送TCP数据
s.recvfrom()     # 接收UDP数据
s.sendto()       # 发送UDP数据
s.getpeername()  # 连接到当前套接字的远端的地址
s.getsockname()  # 当前套接字的地址
s.getsockopt()   # 返回指定套接字的参数
s.setsockopt()   # 设置指定套接字的参数
s.close()        # 关闭套接字

# 面向锁的套接字方法
s.setblocking()  # 设置套接字的阻塞与非阻塞模式
s.settimeout()   # 设置阻塞套接字操作的超时时间
s.gettimeout()   # 得到阻塞套接字操作的超时时间

# 面向文件的套接字的函数
s.fileno()       # 套接字的文件描述符
s.makefile()     # 创建一个与该套接字相关的文件
《Python》网络编程之验证客户端连接的合法性、socketserver模块第1张《Python》网络编程之验证客户端连接的合法性、socketserver模块第2张
官方文档对socket模块下的socket.send()和socket.sendall()解释如下:

socket.send(string[, flags])
Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data.

send()的返回值是发送的字节数量,这个数量值可能小于要发送的string的字节数,也就是说可能无法发送string中所有的数据。如果有错误则会抛出异常。

–

socket.sendall(string[, flags])
Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Unlike send(), this method continues to send data from string until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent.

尝试发送string的所有数据,成功则返回None,失败则抛出异常。

故,下面两段代码是等价的:

#sock.sendall('Hello world
')

#buffer = 'Hello world
'
#while buffer:
#    bytes = sock.send(buffer)
#    buffer = buffer[bytes:]
send和sendall方法

 《Python》网络编程之验证客户端连接的合法性、socketserver模块第3张

二、验证客户端链接的合法性

  如果你想在分布式系统中实现一个简单的客户端链接认证功能,又不像SSL那么复杂,那么利用hmac+加盐的方式来实现

  server端:

import os
import hmac
import socket

def auth(conn):
    msg = os.urandom(32)    # 生成一个随机的字符串
    print(msg, len(msg))    # 32位
    conn.send(msg)  # 发送到client端
    result = hmac.new(secret_key, msg)  # 处理这个随机字符串,得到一个结果
    client_digest = conn.recv(1024)     # 接收client端处理的结果
    if result.hexdigest() == client_digest.decode('utf-8'):
        print('是合法的连接')     # 对比成功可以继续通讯
        return True
    else:
        print('不合法的连接')     # 不成功 close
        return False

secret_key = b'alex_s'   # 相当于'盐'
sk = socket.socket()
sk.bind(('127.0.0.1', 9000))
sk.listen()
conn, addr = sk.accept()
if auth(conn):
    print(conn.recv(1024))
    # 正常的和client端进行沟通
    conn.close()
else:
    conn.close()

sk.close()

  client端:

import hmac
import socket

def auth(sk):
    msg = sk.recv(32)   # 接收随机字符串
    result = hmac.new(key, msg) # 处理这个随机字符串
    res = result.hexdigest()
    sk.send(res.encode('utf-8'))

key = b'alex_s' # '盐',要与server端的一致
sk = socket.socket()
sk.connect(('127.0.0.1', 9000))
auth(sk)    # 调用函数进行验证
# 验证成功就可以通讯了
sk.send(b'hello')

sk.close()
三、socketserver模块

  server端:

import socketserver
# tcp协议的server端就不需要导入socket
class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        conn = self.request
        while 1:
            conn.send(b'hello')
            print(conn.recv(1024))

# 创建一个server, 将服务地址绑定到127.0.0.1  9000
server = socketserver.ThreadingTCPServer(('127.0.0.1', 9000), Myserver)
# 让server永远运行下去,除非强制停止程序
server.serve_forever()

  client端:

import socket

sk = socket.socket()
sk.connect(('127.0.0.1', 9000))
while 1:
    ret = sk.recv(1024)
    print(ret)
    sk.send(b'byebye')
sk.close()

免责声明:文章转载自《《Python》网络编程之验证客户端连接的合法性、socketserver模块》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇利用django框架,手把手教你搭建数据可视化系统(一)ArcMap 9使用技巧下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python(八):python使用lmdb数据库

一、入门代码 LMDB的全称是Lightning Memory-Mapped Database(快如闪电的内存映射数据库),它的文件结构简单,包含一个数据文件和一个锁文件: LMDB文件可以同时由多个进程打开,具有极高的数据存取速度,访问简单,不需要运行单独的数据库管理进程,只要在访问数据的代码里引用LMDB库,访问时给文件路径即可。 让系统访问大量小文...

[Python]IO密集型任务 VS 计算密集型任务

所谓IO密集型任务,是指磁盘IO、网络IO占主要的任务,计算量很小。比如请求网页、读写文件等。当然我们在Python中可以利用sleep达到IO密集型任务的目的。 所谓计算密集型任务,是指CPU计算占主要的任务,CPU一直处于满负荷状态。比如在一个很大的列表中查找元素(当然这不合理),复杂的加减乘除等。 多线程即在一个进程中启动多个线程执行任务。一般来...

在lua环境中使用protobuf

最近在cocos2dx的项目中,需要在LUA脚本层使用protobuf协议。官方已经推出了很多种语言的版本。但唯独LUA版本不全。于是开始研究protobuf在LUA下的实现,将完整的过程记录了下来,希望对其它人能有所帮助。 1、下载protoc-gen-lua 可以通过HG从服务器(hg clonehttps://code.google.com/p/pr...

python网编_进程之开启一个进程

直接上代码: importtime,os from multiprocessing importProcess # 导入模块 deffunc(): time.sleep(1) print('hello',os.getpid()) #os.getpid()的作用是打印进程id if __name__ == '__main__':...

python-数据类型

1.数字 (1)int(integer),整形 (2)float,浮点型,可以认为是小数,但不仅仅是 (3)complex,复数,由实数和叙述部分组成 2. str:字符串 3.布尔型:True 和 False;布尔值 True 和 False 不像字符串,两边没有引号,它们总是以大写字母 T 或 F 开头,后面的字母小写。...

python读取pdf文件

pdfplumber简介 Pdfplumber是一个可以处理pdf格式信息的库。可以查找关于每个文本字符、矩阵、和行的详细信息,也可以对表格进行提取并进行可视化调试。 文档参考https://github.com/jsvine/pdfplumber pdfplumber安装 安装直接采用pip即可。命令行中输入 pip install pdfplumber...