# 手撸http类型socket 加socket长连接管理

本文详细介绍了使用Python自定义的一个结合实际场景的HTTP协议小框架,涉及TCP服务器、Socket编程、URL路由和视图处理。通过MyHttp类实现HTTP请求解析和响应,展示了如何处理GET和POST方法,以及连接池管理。
摘要由CSDN通过智能技术生成

继续上次画的那个图结合我需要使用的场景手撸了一个http协议的小框架

├── application
│   ├── __init__.py
│   ├── model.py
│   ├── __pycache__
│   │   ├── __init__.cpython-38.pyc
│   │   ├── urls.cpython-38.pyc
│   │   └── views.cpython-38.pyc
│   ├── urls.py
│   └── views.py
├── main.py
├── mysocket
│   ├── Base_client.py
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── Base_client.cpython-38.pyc
│   │   ├── __init__.cpython-38.pyc
│   │   └── tcp_server.cpython-38.pyc
│   └── tcp_server.py
├── __pycache__
│   └── setting.cpython-38.pyc
└── setting.py
setting
  #coding=UTF-8
# @Time : 2021/6/21 下午1:59 
# @Author : Ywz
# @File : setting.py 
# @Software: PyCharm
# file declaration:
Tcp_Client_ip = '127.0.0.1'
Tcp_Client_host = 9300
Tcp_Server_ip = '127.0.0.1'
Tcp_Server_host = 9300
Udp_ip = ''
Udp_host = 9300
main
# coding=UTF-8
# @Time : 2021/6/21 下午1:31 
# @Author : Ywz
# @File : main.py 
# @Software: PyCharm
# file declaration: 脚本入口
import setting
from threading import Thread
import threading
from mysocket.tcp_server import TcpServer, SendORMassage
from setting import *

if __name__ == '__main__':
   start = TcpServer(setting.Tcp_Server_ip, setting.Tcp_Server_host)
   start.init()
   socket_client = SendORMassage(start)
   thread = Thread(target=socket_client.accept_client, daemon=True)
   thread.start()
   while True:
       cmd = input("""--------------------------
   输入1:查看当前在线人数
   输入2:给指定客户端发送消息
   输入3:关闭服务端
   输入4:查看当前线程数量
   """)
       if cmd == '1':
           print("--------------------------")
           print("当前在线人数:", len(socket_client.g_conn_pool))
           print("当前在线列表:", socket_client.g_conn_pool)
       elif cmd == '2':
           print("--------------------------")
           index, msg = input("请输入“端口,消息”的形式:").split(",")
           socket_client.g_conn_pool[index].sendall(msg.encode(encoding='utf8'))
       elif cmd == '3':
           exit()
       elif cmd == '4':
           print(len(threading.enumerate()))
mysocket
tcp_server.py
# coding=UTF-8
# @Time : 2021/6/21 下午2:23 
# @Author : Ywz
# @File : tcp_server.py 
# @Software: PyCharm
# file declaration:
import socket
import datetime
import gevent
from application.urls import urlpatterns
from mysocket.Base_client import MySocket, SocketSendORMessage, HttpSendMessage
from threading import Thread


class MyHttp(HttpSendMessage):

   def __init__(self, method: str, uri: str, server: object, server_name: str, current: object):
       super(HttpSendMessage, self).__init__()
       self.method = method
       self.uri = uri
       self.sock_obj = server
       self.server_name = server_name
       self.current = current
       self.prams = None
       self.judge_method()

   def judge_method(self):

       if self.method == "GET":
           print(11231231231)
           _, view = self.get_method()

           result = view(self)

           self.response(result)

       if self.method == "POST":
           _, view = self.get_method()

           result = view(self)

           self.response(result)

   def get_method(self):
       url = None

       if self.uri.find('?'):
           self.uri, self.prams = self.uri.split('?')
           print(self.uri, "12312321312")
           if self.prams.count("&"):
               self.prams = self.prams.split("&")
               __ = {}
               for i in self.prams:
                   _ = (i.split("="))
                   __["%s" % _[0]] = "%s" % _[1]
               self.prams = __
       print(self.prams)
       for i in urlpatterns:
           if i[0] == self.uri:
               url = i

       return url

   def response(self, msg):

       response = '''HTTP/1.1 200 OK
Connection: keep-alive
Data: Thur, 22 Mar ''' + "%s" % self.time() + ''' GMT
Server:PythonWebServer 1.0
Last-Modified: Thur, 22 Mar 2017 19:26:03 GMT
Content-Lenth: ''' + str(len(msg.encode('utf-8'))) + '\nContent-Type:json/html\n\n' + str(msg)
       self.sock_obj.sendall(response.encode('utf-8'))

       self.sock_obj.close()

       self.current.g_conn_pool.pop(self.server_name)

       return None

   def timeFormed(self, form):
       now = datetime.datetime.now()
       return now.strftime(form)

   def time(self):

       week_day = {
           0: 'Mon',
           1: 'Tues',
           2: 'Web',
           3: 'Thur',
           4: 'Fri',
           5: 'San',
           6: 'Sun'
       }
       day = datetime.datetime.now().weekday()
       week = week_day[day]  # 星期
       month_dict = {
           0: 'Jan',
           1: 'Feb',
           2: 'Mar',
           3: 'Apr',
           4: 'May',
           5: 'Jun',
           6: 'Jul',
           7: 'Aug',
           8: 'Sep',
           9: 'Oct',
           10: 'Nov',
           11: 'Dec'
       }
       now = datetime.datetime.now()

       month = month_dict[int(now.strftime('%m'))]  # 月份

       time = week + ', ' + self.timeFormed('%d') + ' ' + month + ' ' + self.timeFormed('%Y %H:%M:%S')

       return time


class TcpServer(MySocket):

   def __init__(self, ip, host):
       super(TcpServer, self).__init__()
       self.ip = ip
       self.host = host

   def init(self):
       """
       初始化服务器
       :return:
       """
       self.g_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
       self.g_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
       self.g_socket_server.bind((self.ip, self.host))
       self.g_socket_server.listen(5)
       print("服务器已启动,等待链接")

   @property
   def show_bank(self):
       return self.g_conn_pool


class SendORMassage(SocketSendORMessage):
   g_conn_pool = {}  # 连接池

   def __init__(self, socket_obj: object):
       super(SocketSendORMessage, self).__init__()
       self.socket_obj = socket_obj

   def accept_client(self):

       while True:
           client, _ = self.socket_obj.g_socket_server.accept()
           print("有端口进行链接了%s" % (str(client)[-7:].replace(r")", '').replace(r">", "")))
           self.g_conn_pool.update(
               {
                   str(client)[-7:].replace(r")", '').replace(r">", ""): client
               }
           )
           thread = Thread(target=self.message_bank,
                           args=(client, str(client)[-7:].replace(r")", '').replace(r">", "")))
           thread.setDaemon(True)
           thread.start()

   def message_bank(self, client, name):

       while True:
           try:

               message = client.recv(1024)
               # print(message)
               if message[4:16] == b'/favicon.ico':
                   client.close()
                   del self.g_conn_pool[name]

                   return
               if len(message) == 0:
                   client.close()
                   # 删除连接
                   del self.g_conn_pool[name]
                   print("有一个客户端下线了。")
                   break
               if message[0:3] == b'GET' or message[0:4] == b'POST':
                   http_msg = message.split()
                   method = http_msg[0].decode()
                   uri = http_msg[1].decode()

                   _ = MyHttp(method=method, uri=uri, server=client, server_name=name, current=self)

                   break



           except Exception as e:
               print("服务端收消息出错%s" % e.args)

####### Base_client.py

# coding=UTF-8
# @Time : 2021/6/21 下午1:36
# @Author : Ywz
# @File : Base_client.py
# @Software: PyCharm
# file declaration: 主要的链接入口
import setting
import socket


class MySocket(object):
   """
   公共类
   """

   Max_listen = 5  # 最大等待数
   g_socket_server = None  # socket 句柄

   def __init__(self):
       pass

   def my_tcp_client(self):
       pass

   def my_tcp_server(self):
       pass

   def my_udp(self):
       pass

   def init(self):
       pass


class SocketSendORMessage(object):

   def __init__(self):
       pass

   def server_name(self):
       pass

   def accept_client(self):
       pass

   def message_bank(self, client, name):
       pass

   def message_http(self):
       pass


class HttpSendMessage(object):

   def __init__(self, method: str, uri: str, server: object):
       self.method = method
       self.uri = uri
       self.sock_obj = server

   def send(self):
       pass

   def message(self):
       pass

   def response(self, msg):
       pass

   def url(self):
       pass

   def get_method(self):
       pass

   def path(self):
       pass
application
views.py
# coding=UTF-8
# @Time : 2021/6/22 上午10:29 
# @Author : Ywz
# @File : views.py 
# @Software: PyCharm
# file declaration:
import copy
import json


def return_bran(self: object):
   _ = self.current.g_conn_pool.copy()

   name = self.server_name
   del _[name]
   msg = {
       "bank": [i for i in _.keys()],
       "num": len([i for i in _.keys()]),
       "local_host": str(name)
   }
   print()
   return json.dumps(msg)


def return_bran_(self):
   print(self)
   return "2"


def return_bran_1(self):
   # print(type(self.prams))
   # print(self.prams)
   return '{"name":"123"}'


def return_bran_2():
   return "4"
urls.py
# coding=UTF-8
# @Time : 2021/6/22 上午10:29 
# @Author : Ywz
# @File : urls.py 
# @Software: PyCharm
# file declaration:
from application import views


urlpatterns = [
   ("/", views.return_bran),
   ("/1", views.return_bran_),
   ("/2", views.return_bran_1),
   ("/3", views.return_bran_2),
   # ("/", views.serach_user),
   # path("/add_user/", views.add_user, methods=["POST"]),
   # path("/select_show_interface/", views.select_show_interface),
   # path("/create_interface/", views.create_interface, methods=["POST"]),
]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值