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)
客户端
原文地址:https://www.cnblogs.com/caixiaowu/p/12489436.html