socket参数的详解
socket.socket(family=AF_INET,type=SOCK_STREAM,proto=0,fileno=None)
创建socket对象的参数说明如下:
参数 | 值 |
---|---|
family | 地址系列应为AF_INET(默认值), AF_INET => ipv4 AF_INET6, => ipv6 AF_UNIX,AF_CAN或AF_RDS.(AF_UNIX 域实际上是使用本地 socket [文件]来通信)同一机器 |
type | 套接字类型应为SOCK_STREAM(默认值),SOCK_DGRAM,SOCK_RAW或其他SOCK_常量之一。 SOCK_STREAM 是基于TCP的,有保障的(即能保证数据正确传送到对方)面向连接的SOCKET,多用于资料传送。 SOCK_DGRAM 是基于UDP的,无保障的面向消息的socket,多用于在网络上发广播信息。 |
proto | 协议号通常为零,可以省略,或者在地址族为AF_CAN的情况下,协议应为CAN_RAW或CAN_BCM之一。 |
fileno | 如果指定了fileno,则其他参数将被忽略,导致带有指定文件描述符的套接字返回。 与socket.fromfd()不同,fileno将返回相同的套接字,而不是重复的。 这可能有助于使用socket.close()关闭一个独立的插座。 |
socket的更多方法介绍(了解)
-
服务端套接字函数
- s.bind() 绑定(主机,端口号)到套接字
- s.listen() 开始TCP监听
- s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来 客户端套接字函数
-
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
(等价于:异常处理+connect 一旦网络不通,作用:返回错误号而不是直接报错)
公共用途的套接字函数
- s.recv() 接收TCP数据
- s.send() 发送TCP数据,send返回值是发送的[字节数量],这个值可能小于要发送的string字节数
-
s.sendall() 发送TCP数据,sendall返回值是None,发送string所有数据
# 下面两个代码等价: #sendall => sock.sendall('Hello world\n') #send => buffer = 'Hello world\n' while buffer: n = sock.send(buffer) buffer = buffer[n:] (切片)
-
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() 创建一个与该套接字相关的文件
hashlib模块
hashlib 这个模块是一堆加密算法的集合体,哈希算法的加密方式不止一种
md5解密网站
应用场景:在需要效验功能时使用
- 用户密码的 => 加密,解密
- 相关效验的 => 加密,解密
哈希算法也叫摘要算法,相同的数据始终得到相同的输出,不同的数据得到不同的输出。
- 哈希将不可变的任意长度的数据,变成具有固定长度的唯一值
- 字典的键值对映射关系是通过哈希计算的,哈希存储的数据是散列(无序)
基本用法
import hashlib
# (1)创建一个md5算法的对象
hs = hashlib.md5()
# (2)把想要加密的字符串通过update更新到hs这个对象
# 参数是二进制字节流
hs.update("wangwendashuaige".encode("utf-8"))
# (3)返回32位16进制的字符串
res = hs.hexdigest()
print(res,len(res))
# 加盐 (加key 只有你自己知道的明文) 目的:增加密码的复杂度
hs = hashlib.md5("Xboyww_".encode("utf-8"))
hs.update("123".encode("utf-8"))
res = hs.hexdigest()
print(res)
# 动态加盐
import random
res = str(random.randrange(10000,100000))
hs = hashlib.md5(res.encode())
hs.update("aabbccdd".encode())
res = hs.hexdigest()
print(res)
"""
# md5 加密效率块 , 通用的加密方法,安全性稍差 位数是32位
# sha 加密效率慢 , 算法相对来说精密,安全性稍高
"""
print("<============================>")
hs = hashlib.sha1()
hs.update("xboyww_123".encode())
res = hs.hexdigest()
# 返回的加密的字符串长度是40位
print(res,len(res))
# 加盐
hs = hashlib.sha1("PPUU".encode())
hs.update("xboyww_123".encode())
res = hs.hexdigest()
print(res)
# sha512
hs = hashlib.sha512()
hs.update("123456".encode())
res = hs.hexdigest()
# 返回的字符春长度是128位
print(res,len(res))
"""
hmac 加密的算法更加不容易破解
"""
import hmac
import os
key = b"123"
msg = b'456'
# hmac里面的new 方法相当于hashlib创建对象和update粘合在一起的操作.
hm = hmac.new(key,msg)
res = hm.hexdigest()
print(res,len(res))
# 随机返回长度为32位的二进制字节流
key = os.urandom(32)
print(key)
hm = hmac.new(key,msg)
res = hm.hexdigest()
print(res,len(res))
文件校验
import hashlib
"""
# 在r模拟下默认read读的是字符,在rb模式默认read读的是字节.
with open("ceshi1.txt",mode="r",encoding="utf-8") as fp:
res = fp.read(3)
print(res)
with open("ceshi1.txt",mode="rb") as fp:
res = fp.read(3)
print(res)
"""
# (1) 针对于小文件的内容校验
def check_md5(file):
with open(file,mode="rb") as fp:
hs = hashlib.md5()
hs.update(fp.read())
return hs.hexdigest()
print(check_md5("ceshi1.txt"))
print(check_md5("ceshi2.txt"))
# (2) 针对于大文件的内容校验
hs = hashlib.md5()
hs.update("昨天晚上\n下雨了".encode())
res = hs.hexdigest()
print(res) #894c4dd4b1f57472322db524e7b6a47f
# 可以连续update到hs对象进行字节流的拼接
hs = hashlib.md5()
hs.update("昨天晚上\n".encode())
hs.update("下雨了".encode())
res = hs.hexdigest()
print(res)
# 方法一
def check_md5(file):
hs = hashlib.md5()
with open(file,mode="rb") as fp:
while True:
content = fp.read(1)
if content:
hs.update(content)
else:
break
return hs.hexdigest()
print("<===>")
print(check_md5("ceshi1.txt"))
print(check_md5("ceshi2.txt"))
# 方法二
print("<===>")
import os
def check_md5(file):
hs = hashlib.md5()
file_size = os.path.getsize(file)
with open(file,mode="rb") as fp:
while file_size:
# read(1) 最多最多读1个,如果文件空了就不读了.
content = fp.read(1)
hs.update(content)
file_size -= len(content)
return hs.hexdigest()
print(check_md5("ceshi1.txt"))
print(check_md5("ceshi2.txt"))
合法性校验
- server服务端
# server 服务端 添加访问的权限验证
import socket
import hmac
import os
def auth(conn,secret_key):
# 随机获取二进制的字节流
msg = os.urandom(32)
# print(msg)
conn.send(msg)
hm = hmac.new(secret_key,msg)
res_serve = hm.hexdigest()
# 接受客户端发给我的字符串
res_client = conn.recv(1024).decode("utf-8")
if res_serve == res_client:
print("合法的链接")
return True
else:
print("不合法的链接")
return False
sk = socket.socket()
sk.bind( ("127.0.0.1",9000) )
sk.listen()
conn,addr = sk.accept()
secret_key = b"wangwendashuaige"
# 收发数据逻辑.
# ...
if auth(conn,secret_key):
# 如果返回真,可以接受客户发来的各种请求
print(conn.recv(1024).decode("utf-8"))
# 四次挥手
conn.close()
# 退还端口
sk.close()
- client客户端
import socket
import hmac
def auth(sk,key):
# 接受服务器发过来的随机二进制字节流
msg = sk.recv(32)
# print(msg)
hm = hmac.new(key,msg)
res = hm.hexdigest()
# 把加密后的字符串发送给服务器
sk.send(res.encode())
sk = socket.socket()
key = b"wangwenchaojidashuaige"
sk.connect( ("127.0.0.1",9000) )
auth(sk,key)
sk.send(b"download")
sk.close()
TCP登陆校验
- server服务端
# ### 服务器登录
import socket
import json
import hashlib
def get_md5_code(usr,pwd):
hs = hashlib.md5(usr.encode())
hs.update(pwd.encode())
return hs.hexdigest()
sk = socket.socket()
sk.bind( ("127.0.0.1",9000) )
sk.listen()
conn,addr = sk.accept()
# 把接受的字节流变成字符串
msg = conn.recv(1024).decode()
# 反序列化字典
dic = json.loads(msg)
# 默认编辑用户不存在
sign = False
with open("userinfo.txt",mode="r",encoding="utf-8") as fp:
for line in fp:
# zhangsan:e7a6d0f97db7ea1c4a0c1c137cbf771c
usr,pwd = line.strip().split(":")
if usr == dic["username"] and pwd == get_md5_code(dic['username'],dic['password']):
res = {"code":1}
res_msg = json.dumps(res).encode()
conn.send(res_msg)
# 该用户找到了,存在
sign = True
break
if sign == False:
res = {"code":0}
res_msg = json.dumps(res).encode()
conn.send(res_msg)
conn.close()
sk.close()
- client客户端
import socket
import hashlib
import json
# 张三 111
# 李四 222
# 王五 333
# 赵柳 444
# 田七 555
sk = socket.socket()
sk.connect( ("127.0.0.1" , 9000) )
# 收发数据的逻辑
usr = input("请输入用户名 :")
pwd = input("请输入您的密码 :")
dic = {"username":usr,"password":pwd,"operate":"login"}
# 把字典序列化成字符串
json_dic = json.dumps(dic)
# 把字符串变成字节流
bytes_msg = json_dic.encode("utf-8")
sk.send(bytes_msg)
# 接受服务器的返回值
res_msg = sk.recv(1024).decode()
# 反序列化成字典
dic_code = json.loads(res_msg)
if dic_code['code']:
print("恭喜你,登录成功")
else:
print("抱歉,登录失败")
sk.close()
- userinfo用户信息
zhangsan:e7a6d0f97db7ea1c4a0c1c137cbf771c
lisi:c79439cf9abcbd6c6d46e45766a9e64a
wangwu:f77599e7005939d280742dc8eb5db89a