zoukankan      html  css  js  c++  java
  • Python开发之路-socket server

    1.socket server实现并发

    服务端:
    
    import socketserver
    
    class Myserver(socketserver.BaseRequestHandler):  #来一个链接产生一个实例
        def handle(self):  #定义了一个通信循环的功能
            print('conn是:',self.request)  #相当于conn  既accept接收到的连接
            print(self.client_address) #相当于addr 既accept接收到的addr地址
            while True:
                try:
                    #收消息
                    data = self.request.recv(1024)
                    if not data: break
                    print('收到客户端的消息是:',data,self.client_address)
    
                    #发消息
                    self.request.sendall(data.upper())
                except Exception as e:
                    print(e)
                    break
    
    if __name__ == '__main__':
        s = socketserver.ThreadingTCPServer(('127.0.0.1',8000),Myserver) #多线程的TCP服务端 第一个参数是IP和端口 第二个参数相当于把通信循环加进去了
        s.serve_forever()  #这两项相当于实现了链接循环 只要有链接进来 直接进入通信循环 执行myserver下的handle方法

    UDP版本:
    #UDP版本
    class Myserver(socketserver.BaseRequestHandler): #来一个链接产生一个实例
    def handle(self): #定义了一个通信循环的功能
    while True:
    data = self.request[0]
    print(data)
    self.request[1].sendto(self.request[0].upper(),self.client_address)
     

    2.socketserver模块

    socketserver中两大类:第一类:server类,处理链接 第二类:request类,处理通信

    server类:

     request类:

    继承关系:

    +------------+
    | BaseServer |
    +------------+
    |
    v
    +-----------+ +------------------+
    | TCPServer |------->| UnixStreamServer |
    +-----------+ +------------------+
    |
    v
    +-----------+ +--------------------+
    | UDPServer |------->| UnixDatagramServer |
    +-----------+ +--------------------+

    Forking:进程

    Threading:线程

    对于TCP来说,self.request = conn 

    对于UDP来说,self.request = (data_bytes,UDP的套接字对象)

    FTP:文件传输协议

    3.认证客户端链接的合法性

    利用hmac+加盐的方式来实现

    客户端:

    #_*_coding:utf-8_*_
    __author__ = 'Linhaifeng'
    from socket import *
    import hmac,os
    
    secret_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)  #将盐和随机产生的32位数组合生成一个新值
        digest=h.digest() #将新值转化为数字
        respone=conn.recv(len(digest)) #接收与数字同等长度的值
        return hmac.compare_digest(respone,digest) #将接收到的值和自己的值做比较,返回一个True或False
    
    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)

    客户端:

    #_*_coding:utf-8_*_
    __author__ = 'Linhaifeng'
    from socket import *
    import hmac,os
    
    secret_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)
    客户端
  • 相关阅读:
    Eclipse SVN 安装注意事项
    Linux添加环境变量与GCC编译器添加INCLUDE与LIB环境变量
    Linux下各种常见环境变量的配置
    Linux下用dump实现备份和还原 ux下用dump实现备份和还原
    Linux dd——备份命令
    linux cpio 备份命令
    Linux服务器的常用备份方法
    tar备份系统
    tar备份系统的方法
    LINUX系统备份
  • 原文地址:https://www.cnblogs.com/caixiaowu/p/12489436.html
Copyright © 2011-2022 走看看