zoukankan      html  css  js  c++  java
  • Day5

    今日学习:

    1.go语言学习

      学习Golang的意外收获:我写的代码执行效率超过了所有用户,哈哈哈

    2.回顾Tcp

       在刚开始学习JAVA的时候,最让人头痛的就是,因为当时初学者刚学习,还没有养成编程思维,无法形象将文

    件传输的操作比作在一个管道里传文件;但是现在写了很多行代码,对文件的传输比喻成流也能理解了。TCP,它的传输文件

    也有recv和send:当服务器做send操作,那么客户端recv,就像管子的一段发送,另一端只能接收一样。

         那么问题来了,当客户端有多台的时候怎么办?不可能只靠一根管子,一个一个传给客户端吧?就在这里我们学习了线程池

    一个服务器和每一台客户机都有一根管子;可是,就算是服务器和每个客户端之间都多了一根管子,有的客户端它老是不接收(或

    发送)消息,我们不能老等着那些不去收发消息的客户端吧?所以,又在这时引入了阻塞/非阻塞的概念,服务端不用去等客户端到

    底什么时候发消息过来,客户端要发消息过来叫一声,服务器就过去了(非阻塞

         但服务端不知道客户端每次发过来的消息是多少,一下长一下短的,其中就出现了将两次消息当作一次发过来的现象,粘包。

    为了解决粘包现象,我们使用了包头[header],包头信息主要做的就是告诉服务端每一次接收多少消息。

       然而之前说的一台服务器和多个客户端之间有多个管子(多线程),在python里其实是不大可行的,因为python具有GIL锁,

    如果你的电脑是双核CPU,就算开了多线程,它最多也就只能利用到一个核,多线程并没有什么帮助,虽然有很多管子,但是每次

    只能用一个。然而回到最开始,服务器和多个客户端就算只有一个管子,那也足够了,当你还没准备好发送消息的时候(遇到IO阻塞

    那我就把管子拿到别人那里去,最大限度的将管子的作用发挥到极限的方式,这种方式叫做协程,遇到IO跳过

         综上,TCP最终版可以成型了:

    1.tcp服务端:

     1 import socket
     2 import threading
     3 import time
     4 
     5 
     6 class tcpServer:
     7     def __init__(self):
     8         self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     9         self.tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    10         self.client_socket_list = list()
    11         self.port = 9527
    12 
    13     def tcp_server_start(self):
    14         """
    15         功能函数,TCP服务端开启的方法
    16         :return: None
    17         """
    18         self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    19         self.tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    20         self.tcp_socket.setblocking(False)
    21         try:
    22 
    23             self.tcp_socket.bind(('', self.port))
    24         except Exception as ret:
    25             self.msg = '请检查端口号
    '
    26             print(self.msg)
    27             print(ret)
    28         else:
    29             self.tcp_socket.listen()
    30             self.sever_th = threading.Thread(target=self.tcp_server_concurrency)
    31             self.sever_th.start()
    32             self.msg = 'TCP服务端正在监听端口:%s
    ' % str(self.port)
    33             print(self.msg)
    34 
    35 
    36     def tcp_server_concurrency(self):
    37         """
    38         功能函数,供创建线程的方法;
    39         使用子线程用于监听并创建连接,使主线程可以继续运行,以免无响应
    40         使用非阻塞式并发用于接收客户端消息,减少系统资源浪费,使软件轻量化
    41         :return:None
    42         """
    43         while True:
    44             try:
    45                 self.client_socket, self.client_address = self.tcp_socket.accept()
    46 
    47             except Exception as ret:
    48                 time.sleep(0.001)
    49 
    50             else:
    51                 self.client_socket.setblocking(False)
    52                 # 将创建的客户端套接字存入列表
    53                 self.client_socket_list.append((self.client_socket, self.client_address))
    54                 self.msg = 'TCP服务端已连接IP:%s端口:%s
    ' % self.client_address
    55                 print(self.msg)
    56             # 轮询客户端套接字列表,接收数据
    57             for client, address in self.client_socket_list:
    58                 try:
    59                     recv_msg = client.recv(1024)
    60                 except Exception as ret:
    61                     pass
    62                 else:
    63                     if recv_msg:
    64                         msg = recv_msg.decode('utf-8')
    65                         self.msg = '来自IP:{}端口:{}:
    {}
    '.format(address[0], address[1], msg)
    66                         print(self.msg)
    67                     else:
    68                         client.close()
    69                         self.client_socket_list.remove((client, address))
    70     def tcp_server_send(self):
    71         send_msg = input('')
    72         for client, address in self.client_socket_list:
    73             client.send(send_msg.encode('utf-8'))
    74         self.msg = 'TCP服务端已发送
    '
    75         print(self.msg)
    76 
    77 if __name__ == '__main__':
    78     tcpS=tcpServer()
    79     tcpS.tcp_server_start()
    80     while True:
    81         tcpS.tcp_server_send()
    View Code

    2.tcp客户端:

    import socket
    import threading
    
    
    class TcpClient:
        def __init__(self):
            self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.ip="127.0.0.1"
            self.port=9527
    
        def tcp_client_start(self):
            """
            功能函数,TCP客户端连接其他服务端的方法
            :return:
            """
            self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            try:
                self.address = (str(self.ip), int(self.port))
            except Exception as ret:
                self.msg = '请检查目标IP,目标端口
    '
                print(self.msg)
            else:
                try:
                    self.msg = '正在连接目标服务器
    '
                    print(self.msg)
                    self.tcp_socket.connect(self.address)
                except Exception as ret:
                    self.msg = '无法连接目标服务器
    '
                    print(self.msg)
                    print(ret)
                else:
                    self.client_th = threading.Thread(target=self.tcp_client_concurrency)
                    self.client_th.start()
                    self.msg = 'TCP客户端已连接IP:%s端口:%s
    ' % self.address
                    print(self.msg)
    
        def tcp_client_concurrency(self):
            """
            功能函数,用于TCP客户端创建子线程的方法,阻塞式接收
            :return:
            """
            while True:
                recv_msg = self.tcp_socket.recv(1024)
                if recv_msg:
                    msg = recv_msg.decode('utf-8')
                    self.msg = '来自IP:{}端口:{}:
    {}
    '.format(self.address[0], self.address[1], msg)
                    print(self.msg)
                else:
                    self.tcp_socket.close()
                    self.msg = '从服务器断开连接
    '
                    print(self.msg)
                    break
        def tcp_client_send(self):
            send_msg = input('')
            self.tcp_socket.send(send_msg.encode('utf-8'))
            self.msg = 'TCP客户端已发送
    '
    
    if __name__ == '__main__':
        tcpC = TcpClient()
        tcpC.tcp_client_start()
        while True:
            tcpC.tcp_client_send()
    View Code

    功能如下:

      -两端可以同时收发消息

      -非阻塞方式减少服务器压力

      -子线程用于监听并创建连接,使主线程可以继续运行,以免无响应

      -非阻塞式并发用于接收客户端消息,减少系统资源浪费


    3.防优酷项目业务逻辑层学习:

      管理员业务需求抽取:

      -管理员:1.上传电影

           2.删除电影

           3.更新公告

     3.1 上传电影功能

      获取一个从客户端接受来的字典back_dict,

      1.从字典获取属性:名字,大小,是否免费,电影MD5码,上传者id

      2.根据电影名,使用tcp从客户端管理员获取电影,并存放于设定的好目录文件夹下

      3.对数据库进行更新,把刚才下好的电影信息进行保存

     

     3.2删除电影功能

      获取一个从客户端接受来的字典back_dict,

      1.从字典获取属性:需要删除的电影id

      2.从数据库中搜索出该电影,并返回一个相对应的电影对象

      3.对该电影的is_delete设置为1,1为已经删除

      4.对数据库进行更新,把刚才做好删除标记的电影信息进行保存

      

       3.3 更新公告功能

      获取一个从客户端接受来的字典back_dict,

      1.从字典获取属性:标题名称,内容,时间,管理员的id

      2.根据属性,获得对应的notice对象

      3.对内容进行保存

      4.对数据库进行更新,把刚才做好删除标记的电影信息进行保存

       

      业务层学习总结:

        1.业务层做的事是,向数据层获取数据,向界面层提交,实现需求。

      2.当业务层需要ORM做复杂一点的操作,例如多表查询,按需输出这,为了实现这些操作,需要向ORM里写一些新的获取数据层的手段方法,反而不利于开发效率吧?

      3.在细节上,例如判断上传的电影是否存在,那么根据select()返回一个对象,如果存在就返回一个对象;这样的操作会不会太臃肿?因为毕竟我只是需要知道它存在就行了

      4.在业务层上,conn始终作为一个参数参与进行业务实现,这样做会不会有什么风险问题?我可不可以将收发信息的功能写到lib里,使得业务逻辑层不直接与客户连接混在一起?

    业务层管理员代码实现:

      

    import datetime
    
    import os
    
    from conf import settings
    from lib import common
    from orm import models
    
    #上传电影功能
    # @common.login
    def upload_movie_interface(back_dic):
        movie_size = back_dic.get('movie_size')
        movie_name = back_dic.get('movie_name')
        # movie_new_name = common.get_session(movie_name) + movie_name
        movie_new_name = movie_name
        movie_path = os.path.join(settings.DOWNLOAD_MOVIES_PATH, movie_new_name)
        # recv_data = 0
        # with open(movie_path, 'wb') as f:
        #     while recv_data < movie_size:
        #         data = conn.reader.read(100)
        #         f.write(data)
        #         recv_data += len(data)
    
        # 2.存储电影信息于电影表中
        movie_obj = models.Movie(
            name=movie_new_name,
            is_free=back_dic.get('is_free'),
            is_delete=0,
            file_md5=back_dic.get('movie_md5'),
            path=movie_path,
            create_time=str(datetime.datetime.now()),
            user_id=back_dic.get('user_id')
        )
    
        movie_obj = movie_obj.save()
        print(movie_obj.__dict__)
        # data = {'flag': True, 'msg': '电影上传成功!'}
        # conn.writer.write(data)
    
    #删除电影
    def delete_movie_interface(back_dic, ):
        movie_id = back_dic.get('movie_id')
        movie_obj = models.Movie.select(models.Movie(),whereStr="id={0}".format(movie_id))[0]
        print(movie_obj.is_delete)
        movie_obj.is_delete = 1  # 0 --> 1
        movie_obj.update()
    
        send_dic = {
            'flag': True,
            'msg': '电影删除成功!'
        }
        # common.send_msg(send_dic, conn)
    
    #发送公告
    def send_notice_interface(back_dic, ):
    
        notice_obj = models.Notice(
            title=back_dic.get('title'),
            content=back_dic.get('content'),
            create_time=str(datetime.datetime.now()),
            user_id=back_dic.get('user_id')
        )
        notice_obj = notice_obj.select(whereStr="movie_id={0}".format(notice_obj.user_id))[0]
        # 插入公告
        notice_obj.save()
    
        send_dic = {
            'msg': '公告发布成功!'
        }
    
        # common.send_msg(send_dic, conn)
    
    
    
    back_dict={'movie_size':10,
               'movie_name':'盗梦空间',
               'is_free':'0',
                'movie_md5': '123456',
                "movie_id":2,
                 'user_id':5
    }
    # upload_movie_interface(back_dict)
    delete_movie_interface(back_dict)
    # send_notice_interface(back_dict)
    

      

        

  • 相关阅读:
    使用iOS网络请求
    Invalid RNPermission 'ios.permission.xxx'. should be one of: ( )
    React Native 报错 Error: spawn EACCES 权限
    React Native 适配Android物理返回键,实现连续两次点击退出
    图解:平衡二叉树,AVL树
    NOIP 骗分技巧
    P1004 方格取数
    5. 最长回文子串
    全链路压测自动化实践
    深度学习在美团配送ETA预估中的探索与实践
  • 原文地址:https://www.cnblogs.com/ygy1997/p/11799869.html
Copyright © 2011-2022 走看看