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)

客户端

 

版权声明:本文为caixiaowu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/caixiaowu/p/12489436.html