补充:
send()与sendall()
在python socket编程中,有两个发送TCP的函数,send()与sendall(),区别如下:
socket.send(string[, flags]) 发送TCP数据,返回发送的字节大小。这个字节长度可能少于实际要发送的数据的长度。换句话说,这个函数执行一次,并不一定能发送完给定的数据,可能需要重复多次才能发送完成。
data = "something you want to send"
while True:
len = s.send(data[len:])
if not len:
break
socket.sendall(string[, flags]) 看懂了上面那个,这个函数就容易明白了。发送完整的TCP数据,成功返回None,失败抛出异常
data = "something you want to send"
s.sendall(data)
getpeername和getsoketopt的用法
服务器端代码
import socket
sk =socket.socket()
sk.bind(('127.0.0.1',9000))
sk.listen()
conn,addr =sk.accept()
conn.send(b'gdadfadsd')
print('getpeername:\n',conn.getpeername()) #连接到当前套接字的远端地址.
print('getsocketop:\n',sk.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR))#返回指定套接字的参数
conn.recv(1024)
conn.close()
sk.close()
结果
客户端代码
import socket sk=socket.socket() sk.connect(('127.0.0.1',9000)) sk.send(b'helllo') ret =sk.recv(1024) print(ret) sk.close()
一 、socketv 验证客户端链接的合法性
对server与client双向传输的数据进行md5加密操作()
import hashlib import socket sk =socket.socket() sk.bind(('127.0.0.1',8083)) sk.listen() conn,addr =sk.accept() send_str ="helloword" secret_key = b'hello' conn.send(send_str.encode('utf-8'))#把字符串发过去 #留着比对用 md5_obj =hashlib.md5(secret_key)#md5加密 md5_obj.update(send_str.encode('utf-8')) #send_str进行加密,留着然后和client返回的做对比 sercret_ret =md5_obj.hexdigest() # 摘要之后是一串字符串. print(sercret_ret) # conn.send(sercret_ret.encode('utf-8')) if sercret_ret ==conn.recv(1024).decode('utf-8'): print("客户端为合法身份") else: print("客户端为非法身份")
import socket import hashlib ADDR = ('127.0.0.1',8083) sk =socket.socket() sk.connect(ADDR) secret_key = b'hello' md5_obj =hashlib.md5(secret_key) msg = sk.recv(1024) print(msg.decode('utf-8')) md5_obj.update(msg) secret_ret =md5_obj.hexdigest()#摘要结果为字符串格式. print(secret_ret) sk.send(secret_ret.encode('utf-8'))
对server与client双向传输的数据进行md5加密操作(),然后制作了一个小聊天工具
import os import socket import hashlib def check_client(conn): secret_key =b'egg'#秘钥 send_str ='这是一个随机的字符串' conn.send(send_str.encode('utf-8')) md5_obj =hashlib.md5(secret_key) #加盐也要转换成bytes类型 md5_obj.update(send_str.encode('utf-8'))# update摘要必须是byte类型. secret_ret =md5_obj.hexdigest() #摘要后的结果字符串类型str if conn.recv(1024).decode('utf-8')==secret_ret: print('合法的客户端') return True else: print('非法的客户端') return False sk =socket.socket() sk.bind(('127.0.0.1',8002)) sk.listen() conn,addr =sk.accept() ret = check_client(conn) while ret : inp = input('>>>>') conn.send(inp.encode('utf-8')) msg = conn.recv(1024) print(msg.decode('utf-8')) conn.close() sk.close()
import socket import hashlib sk = socket.socket() sk.connect(('127.0.0.1',8002)) recv =sk.recv(1024) #用相同的手法对这个字符串进行摘要. secret_key = b'egg'#秘钥 md5_obj = hashlib.md5(secret_key) #加盐的方式进行md5加密. md5_obj.update(recv) #摘要以bytes类型摘要. ret = md5_obj.hexdigest() #加密后是字符串的形式. sk.send(ret.encode('utf-8')) # 发送以bytes类型发送. msg =sk.recv(1024) if msg: print(msg.decode('utf-8')) while True: inp = input(">>>>") sk.send(inp.encode('utf-8')) msg =sk.recv(1024) print(msg.decode('utf-8')) sk.close()
验证客户端合法性的方法HMAC
import os import hmac #内置模块 #简单的网络编程中的客户端合法性验证。 ret =os.urandom(32) print(os.urandom(32))#每次运行都会生成一个32位的随机字节 # 输出结果 # b'\xa8=\xd2}\xe2\xdcc\xbd\xc3X\xf4\xe2\xcfW\xe02LD\xd8\xa0\x10e\xbcR0\x02\xf8\xc1\x0ez9\xf1' hmac_obj =hmac.new(b'egg',ret) ret2 =hmac_obj.digest() print(ret2) # 输出结果 # b'\xf9\x0c\xa8{\xb1\xb0\xf7\xda\xa7\xb9\x8d\xe3\x1f\x9e\xa0\x87'
#服务器端
import hmac import os import socket import hmac def check_client(conn): secret_key =b'egg'#秘钥 send_str = os.urandom(32) conn.send(send_str) md5_obj =hmac.new(secret_key,send_str) secret_ret =md5_obj.digest() hmac #摘要后的结果是bytes if conn.recv(1024)==secret_ret: 两个bytes类型进行对比 print('合法的客户端') return True else: print('非法的客户端') return False sk =socket.socket() sk.bind(('127.0.0.1',8002)) sk.listen() conn,addr =sk.accept() ret = check_client(conn) while ret : inp = input('>>>>') conn.send(inp.encode('utf-8')) msg = conn.recv(1024) print(msg.decode('utf-8')) conn.close() sk.close()
# sk.connect(('127.0.0.1',8002)) # recv =sk.recv(1024) # #用相同的手法对这个字符串进行摘要. # secret_key = b'egg'#秘钥 # md5_obj = hashlib.md5(secret_key) #加盐的方式进行md5加密. md5_obj=hmac.new(secret_key,recv) # ret = md5_obj.digest() #加密后是字符串的形式. # sk.send(ret.encode('utf-8')) # 发送以bytes类型发送. # sk.send(ret) # # msg =sk.recv(1024) # if msg: # print(msg.decode('utf-8')) # while True: # inp = input(">>>>") # sk.send(inp.encode('utf-8')) # msg =sk.recv(1024) # print(msg.decode('utf-8')) # sk.close()
二、socketserver
#服务器端
import socketserver
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
self.request.send(b'hello') #conn
msg=self.request.recv(1024).decode('utf-8')
print(msg)
server = socketserver.ThreadingTCPServer(
('127.0.0.1',9000),
MyServer)
server.serve_forever()
#客户端
import socket
sk =socket.socket()
sk.connect(('127.0.0.1',9000))
print(sk.recv(1024))
msg= input(">>>>").encode('utf-8')
sk.send(msg)
sk.close()
import json import hashlib import socketserver def md5_pwd(user,pwd): md5_obj = hashlib.md5(user.encode('utf-8')) md5_obj.update(pwd.encode('utf-8')) ret = md5_obj.hexdigest() return ret def login(userinfo): user_dic = json.loads(userinfo) passwd = md5_pwd(user_dic['username'], user_dic['passwd']) with open('userinfo') as f: for line in f: user, pwd = line.split('|') if user_dic['username'] == \ user and passwd == pwd: print('登录成功') break class MyServer(socketserver.BaseRequestHandler): def handle(self): userinfo = self.request.recv(1024).decode('utf-8') login(userinfo) server = socketserver.ThreadingTCPServer( ('127.0.0.1',9000), MyServer) server.serve_forever()
import json import socket ADDR = ('127.0.0.1',9000) def get_socket(): sk = socket.socket() sk.connect(ADDR) return sk # 输入账号 username = input('username >>>') passwd = input('password >>>') if username.strip() and passwd.strip(): sk = get_socket() dic = {'username':username,'passwd':passwd} str_dic = json.dumps(dic) sk.send(str_dic.encode('utf-8')) sk.close()