博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
认证客户端的链接与socketserver实现并发
阅读量:5738 次
发布时间:2019-06-18

本文共 6193 字,大约阅读时间需要 20 分钟。

from socket import *import hmac,ossecret_key=b'linhaifeng bang bang bang'def conn_auth(conn):    '''    认证客户端链接    :param conn:    :return:    '''    print('开始验证新链接的合法性')    msg=os.urandom(32)    conn.sendall(msg)    h=hmac.new(secret_key,msg)    digest=h.digest()    respone=conn.recv(len(digest))    return hmac.compare_digest(respone,digest)def data_handler(conn,bufsize=1024):    if not conn_auth(conn):        print('该链接不合法,关闭')        conn.close()        return    print('链接合法,开始通信')    while True:        data=conn.recv(bufsize)        if not data:break        conn.sendall(data.upper())def server_handler(ip_port,bufsize,backlog=5):    '''    只处理链接    :param ip_port:    :return:    '''    tcp_socket_server=socket(AF_INET,SOCK_STREAM)    tcp_socket_server.bind(ip_port)    tcp_socket_server.listen(backlog)    while True:        conn,addr=tcp_socket_server.accept()        print('新连接[%s:%s]' %(addr[0],addr[1]))        data_handler(conn,bufsize)if __name__ == '__main__':    ip_port=('127.0.0.1',9999)    bufsize=1024    server_handler(ip_port,bufsize)
服务端
from socket import *import hmac,ossecret_key=b'linhaifeng bang bang bang'def conn_auth(conn):    '''    验证客户端到服务器的链接    :param conn:    :return:    '''    msg=conn.recv(32)    h=hmac.new(secret_key,msg)    digest=h.digest()    conn.sendall(digest)def client_handler(ip_port,bufsize=1024):    tcp_socket_client=socket(AF_INET,SOCK_STREAM)    tcp_socket_client.connect(ip_port)    conn_auth(tcp_socket_client)    while True:        data=input('>>: ').strip()        if not data:continue        if data == 'quit':break        tcp_socket_client.sendall(data.encode('utf-8'))        respone=tcp_socket_client.recv(bufsize)        print(respone.decode('utf-8'))    tcp_socket_client.close()if __name__ == '__main__':    ip_port=('127.0.0.1',9999)    bufsize=1024    client_handler(ip_port,bufsize)
客户端

基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环

socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题)

server类:

request类:

 

 

查找属性的顺序:ThreadingTCPServer->ThreadingMixIn->TCPServer->BaseServer

  1. 实例化得到ftpserver,先找类ThreadingTCPServer的__init__,在TCPServer中找到,进而执行server_bind,server_active
  2. 找ftpserver下的serve_forever,在BaseServer中找到,进而执行self._handle_request_noblock(),该方法同样是在BaseServer中
  3. 执行self._handle_request_noblock()进而执行request, client_address = self.get_request()(就是TCPServer中的self.socket.accept()),然后执行self.process_request(request, client_address)
  4. 在ThreadingMixIn中找到process_request,开启多线程应对并发,进而执行process_request_thread,执行self.finish_request(request, client_address)
  5. 上述四部分完成了链接循环,本部分开始进入处理通讯部分,在BaseServer中找到finish_request,触发我们自己定义的类的实例化,去找__init__方法,而我们自己定义的类没有该方法,则去它的父类也就是BaseRequestHandler中找....

源码分析总结:

基于tcp的socketserver我们自己定义的类中的

  1.   self.server即套接字对象
  2.   self.request即一个链接
  3.   self.client_address即客户端地址

基于udp的socketserver我们自己定义的类中的

  1.   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)>)
  2.   self.client_address即客户端地址

 

import socketserverimport structimport jsonimport osclass FtpServer(socketserver.BaseRequestHandler):    coding='utf-8'    server_dir='file_upload'    max_packet_size=1024    BASE_DIR=os.path.dirname(os.path.abspath(__file__))    def handle(self):        print(self.request)        while True:            data=self.request.recv(4)            data_len=struct.unpack('i',data)[0]            head_json=self.request.recv(data_len).decode(self.coding)            head_dic=json.loads(head_json)            # print(head_dic)            cmd=head_dic['cmd']            if hasattr(self,cmd):                func=getattr(self,cmd)                func(head_dic)    def put(self,args):        file_path = os.path.normpath(os.path.join(            self.BASE_DIR,            self.server_dir,            args['filename']        ))        filesize = args['filesize']        recv_size = 0        print('----->', file_path)        with open(file_path, 'wb') as f:            while recv_size < filesize:                recv_data = self.request.recv(self.max_packet_size)                f.write(recv_data)                recv_size += len(recv_data)                print('recvsize:%s filesize:%s' % (recv_size, filesize))ftpserver=socketserver.ThreadingTCPServer(('127.0.0.1',8080),FtpServer)ftpserver.serve_forever()
FtpServer
import socketimport structimport jsonimport osclass MYTCPClient:    address_family = socket.AF_INET    socket_type = socket.SOCK_STREAM    allow_reuse_address = False    max_packet_size = 8192    coding='utf-8'    request_queue_size = 5    def __init__(self, server_address, connect=True):        self.server_address=server_address        self.socket = socket.socket(self.address_family,                                    self.socket_type)        if connect:            try:                self.client_connect()            except:                self.client_close()                raise    def client_connect(self):        self.socket.connect(self.server_address)    def client_close(self):        self.socket.close()    def run(self):        while True:            inp=input(">>: ").strip()            if not inp:continue            l=inp.split()            cmd=l[0]            if hasattr(self,cmd):                func=getattr(self,cmd)                func(l)    def put(self,args):        cmd=args[0]        filename=args[1]        if not os.path.isfile(filename):            print('file:%s is not exists' %filename)            return        else:            filesize=os.path.getsize(filename)        head_dic={
'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize} print(head_dic) head_json=json.dumps(head_dic) head_json_bytes=bytes(head_json,encoding=self.coding) head_struct=struct.pack('i',len(head_json_bytes)) self.socket.send(head_struct) self.socket.send(head_json_bytes) send_size=0 with open(filename,'rb') as f: for line in f: self.socket.send(line) send_size+=len(line) print(send_size) else: print('upload successful')client=MYTCPClient(('127.0.0.1',8080))client.run()
FtpClient

 

转载于:https://www.cnblogs.com/wanghaohao/p/7428367.html

你可能感兴趣的文章
有利于seo优化的网站地图不能取巧
查看>>
快照产品体验优化
查看>>
ASCII
查看>>
ibatis SqlMap not found
查看>>
Android SD卡创建文件和文件夹失败
查看>>
Ubuntu 14.04 vsftp refusing to run with writable root inside chroot问题解决方法
查看>>
Intellij IDEA远程调试tomcat
查看>>
hadoop的学习论坛
查看>>
Struts2 学习小结
查看>>
烂泥:wordpress迁移到docker
查看>>
.扒渣机的性能及优势 
查看>>
Linux下磁盘保留空间的调整,解决df看到的空间和实际磁盘大小不一致的问题
查看>>
RSA 生成公钥、私钥对
查看>>
测试工具综合
查看>>
asp.net中调用COM组件发布IIS时常见错误 80070005解决方案
查看>>
分享一段ios数据库代码,包括对表的创建、升级、增删查改
查看>>
如何书写高质量的jQuery代码
查看>>
Activity的生命周期整理
查看>>
【记录】JS toUpperCase toLowerCase 大写字母/小写字母转换
查看>>
在 Linux 系统中安装Load Generator ,并在windows 调用
查看>>