GPRS测试服务端

项目是通过设备的GPRS和服务器端连接,然后把当前的时间发送到设备端

这里只是服务端的代码

import os
import sys
import time
import traceback
import http.client
import selectors
import socket
from datetime import datetime
from PyQt5.QtGui import QIcon, QFont, QTextCursor
from PyQt5.QtCore import QCoreApplication, pyqtSignal, QThread, QObject
from PyQt5.QtWidgets import (QApplication, QWidget, QLabel, QLineEdit, QTextEdit, QPushButton ,
                             QGroupBox, QVBoxLayout, QHBoxLayout, QGridLayout)



class GprsTestTcpServerWork(QObject):

    def __init__(self,server_port):
        super().__init__()
        self.tcp_server_selector = selectors.DefaultSelector()

        self.tcp_server_socket = socket.socket()
        self.tcp_server_port = server_port
        self.tcp_server_socket.bind(('',self.tcp_server_port))
        self.tcp_server_socket.listen(100)
        self.tcp_server_socket.setblocking(False)

        self.tcp_server_selector.register(self.tcp_server_socket,selectors.EVENT_READ,self.tcp_server_accept)
        self.tcp_server_run = True

        '''
        accept在外部socket连接进来也就是收到EVENT_READ消息时候调用到
        sock.accpet会获取到连接进来的套接字以及地址
        这里的conn套接字和外面的socket套接字不是一个概念
        这个套接字是用来传输数据用的, 当然连接进来的套接字也要设置为非阻塞的
        因为要在这里也实现异步操作,这里就是异步的读取
        这里也将对应的读取函数注册到这个套接字上,
        所以在读取的时候就会将要读取的内容从对应的套接字上接收回来
        当然看到下面的read函数,在读取之后再反馈给对应的套接字一个字符串
        最后再关闭这次连接
        '''

    #注意这里的参数个数pyqtSignal后面跟几个参数要看准
    show_msg_signal = pyqtSignal(str,int)

    def tcp_server_accept(self,sock,mask):
        conn,addr = sock.accept()
        '''send message to ui'''
        print("accepted",conn,'from',addr)

        msg = 'accepted' + (str)(conn) + 'from' + (str)(addr)
        self.show_msg_signal.emit(msg,0)

        conn.setblocking(False)
        self.tcp_server_selector.register(conn,selectors.EVENT_READ,self.tcp_server_read)

    def tcp_server_read(self,conn,mask):
        rece_data = conn.recv(100).decode('utf-8')

        if rece_data:
            print("receive data = %s"%rece_data)
            '''send message to ui'''
            msg = 'receive data:' + rece_data
            self.show_msg_signal.emit(msg,0)

            send_data = self.tcp_server_get_send_data_ready(rece_data)

            print("send data = %s"%send_data)

            msg = 'send data:' + send_data
            self.show_msg_signal.emit(msg,0)
            conn.send(send_data.encode('utf-8'))
        else:
            print("close socket")
            msg = 'close socket'
            self.show_msg_signal.emit(msg,0)
            self.tcp_server_selector.unregister(conn)
            conn.close()

    def tcp_server_get_send_data_ready(self,recv_data):
        char_pos = recv_data.find("##");

        if char_pos == -1:
            msg = 'illegal string'
            self.show_msg_signal.emit(msg,0)
            return "illegal string"

        send_data = recv_data[0:char_pos + 2] + "UTCtime:";

        now = datetime.now()
        #print('data time now:')
        #print(now)

        now_utc_time = ((str)((int)((datetime.now()).timestamp())))
        #print(now_utc_time)
        send_data += now_utc_time;

        return send_data

    def tcp_server_loop(self):
        while self.tcp_server_run == True:
            print("begin loop....")
            socket_events = self.tcp_server_selector.select()
            '''
            Here events is a list type.In events it can include many events,
            every event include a iterator.you can print it 
            '''
            print("socket_events %d"%(len(socket_events)))

            for socket_key, socket_style in socket_events:
                socket_callback = socket_key.data
                socket_callback(socket_key.fileobj,socket_style)

    def tcp_server_loop_end(self):
        print("tcp_server_loop_end")
        msg = 'tcp_server_loop_end'
        self.show_msg_signal.emit(msg,0)
        if self.tcp_server_run == True:
            self.tcp_server_run = False

'''GprsTestServer'''
class GprsTestServer(QWidget):

    def __init__(self):
        super().__init__()
        self.gprs_test_server_init_ui()

    def gprs_test_server_init_ui(self):
        '''ui 的初始化'''

        '''
        先通过QFont 类来获取当前UI上所要用的font
        如果没有下面的setFamily或者setPointSize的话就会是默认的字体和大小了
        默认字体好像是宋体,字体也比较小
        这里字体设置是Courier New,字体大小是10
        '''
        self.server_font = QFont()

        self.server_font.setFamily("Courier New")
        self.server_font.setPointSize(10)
        '''如果没有调用setFont则字体不会起作用'''
        self.setFont(self.server_font)

        '''
        setGeometry 设置窗体的位置和大小
        从屏幕的500,300坐标点为左边顶点,显示一个650x300的窗体
        '''
        self.setGeometry(500,300,650,300)
        '''
        setFixedSize 为设置窗体的最大尺寸为650x400,这句一旦设置了则前面的300就不起作用了,直接高度固定为了400
        不信你试试,哈哈
        如果不调用这句的话,则窗体是可以最大化的,调用之后右上角最大化的图标就置灰色了
        试了下setFixedSize(650,800)窗体会被拉的很高
        '''
        self.setFixedSize(650,400)
        '''这句设置窗体的title'''
        self.setWindowTitle('GPRS_Test_Server')
        '''设置窗体的ICON'''
        self.setWindowIcon(QIcon('GPRS_Test_Server.ico'))

        '''创建网格Box'''
        self.gprs_test_server_create_grid_group_box()
        '''创建下面的网格layout'''
        '''
        这里分成两个部分,上面部分是GroupBox,下面部分其实就是简单的一个QTexEdit
        但是也要分成两个Layout
        因为整个窗体的主窗体layout是被设置为QVBoxLayout在其上做上下的控件添加的
        '''
        self.gprs_test_server_create_grid_layout_down()

        '''
        先创建一个QVBoxLayout的main_layout。
        其他的控件都是依附在整个main_layout上的
        刚开始我想下面的控件只有个QTextEdit,直接就可以加在main_layout的窗体上
        但是发现main_layout的方法是addLayout,
        事实证明使用#2222代替#1111还是可行的
        '''
        main_layout = QVBoxLayout()
        '''
        QHBoxLayout,按照从左到右的顺序进行添加控件
        QVBoxLayout,按照从上到下的顺序进行添加控件
        '''
        hbox_layout = QHBoxLayout()
        hbox_layout.addWidget(self.gridGroupBox)

        main_layout.addLayout(hbox_layout)
        #main_layout.addLayout(self.grid_layout_down)#1111
        main_layout.addWidget(self.msg_textedit) #2222

        self.setLayout(main_layout)

        self.show()


    def gprs_test_server_init_work(self):
        '''创建工作线程,当按下start button的时候就让线程运行起来'''
        '''和MFC中的工作线程类似'''
        self.server_thread = QThread()

        '''GprsTestServerWork继承Qobject,这里要使用到signal 和 slot'''
        '''GprsTestTcpServerWork中包含要在子线程中运行的代码,以及在子线程运行过程中需要发回主线程的信号'''
        self.server_work = GprsTestTcpServerWork(self.server_port_int)

        '''server_thread和进程通信可以通过show_msg_signal,通过show_msg_signal emit发送string'''
        self.server_work.show_msg_signal.connect(self.gprs_test_server_show_message)

        '''将实例化的GprsTestTcpServerWork移到子线程中'''
        self.server_work.moveToThread(self.server_thread)

        '''线程开始start和结束stop的时候绑定对应的动作'''
        self.server_thread.started.connect(self.server_work.tcp_server_loop)
        self.server_thread.finished.connect(self.server_work.tcp_server_loop_end)


    def gprs_test_server_create_grid_group_box(self):
        '''GroupBox ????'''
        self.gridGroupBox = QGroupBox('GPRS_Test_Server Setting');
        '''创建一个网格layout'''
        grid_layout = QGridLayout()

        '''QLable 应该是静态文字'''
        self.server_addr = QLabel('Server Addr:')
        self.server_port = QLabel('Server Port:')
        pc_name = socket.getfqdn(socket.gethostname())
        print('pc_name = %s'%pc_name)
        self.local_ip = socket.gethostbyname(pc_name)
        print(self.local_ip)
        self.server_ip = QLabel(self.local_ip)

        '''QPushButton就是普通的Button可以按下的'''
        self.server_start = QPushButton('Start',self)
        '''start action to do'''
        self.server_start.clicked.connect(self.gprs_test_server_btn_start)

        self.server_stop = QPushButton('Stop',self)
        self.server_stop.setEnabled(False)
        self.server_stop.clicked.connect(self.gprs_test_server_btn_stop)
        '''stop action to do'''

        '''
        Edit 控件,不知道QLineEdit和QTextEdit的区别
        下面有QTextEdit控件,大概可能是QTextEdit是不能编辑的吧
        '''
        self.server_port_edit = QLineEdit()
        '''设置控件的灰色默认填充字符串'''
        self.server_port_edit.setPlaceholderText("<=65535")

        '''设置空白的???'''
        grid_layout.setSpacing(10)

        '''
        QGridLayout.addWidget(QWidget * widget, int row, int column, Qt.Alignment alignment = 0 )
        widget 要添加的组件
        row 组件要添加到的行数
        column 组件要添加到的列数
        '''
        grid_layout.addWidget(self.server_addr,1,0)

        grid_layout.addWidget(self.server_ip,1,1)
        grid_layout.addWidget(self.server_start,1,2)

        grid_layout.addWidget(self.server_port,2,0)
        grid_layout.addWidget(self.server_port_edit,2,1)
        grid_layout.addWidget(self.server_stop,2,2)

        grid_layout.setColumnStretch(1,10)
        self.gridGroupBox.setLayout(grid_layout)


        '''
        QGridLayout.addWidget(QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt.Alignment alignment = 0)
        当添加的组件跨越很多行或者列的时候,使用该方法。
        QWidget:为所添加的组件
        fromRow:为组件起始的行数
        fromColumn:为组件起始的列数
        rowSpan:为组件跨越的行数
        columnSpan:为组件跨越的列数
        alignment:对齐的方式
        '''

        '''
        main_layout.addWidget(self.msg_textedit) #2222
        从前面这句就可以看出来可以只用定义一个
        QTextEdit就可以,也就是说这个函数中只用做一个定义
        self.msg_textedit = QTextEdit就可以
        '''
    def gprs_test_server_create_grid_layout_down(self):
        '''这个方法命名有点low了'''
        self.grid_layout_down = QGridLayout()

        self.msg_textedit = QTextEdit()

        self.grid_layout_down.addWidget(self.msg_textedit,1,0)

        '''
        msg_style 这里定义为需要用哪种颜色
        msg_style 0:蓝色  1:红色
        msg参数是要显示的message内容
        '''
    def gprs_test_server_show_message(self,msg,msg_style):
        now_time = time.strftime("%m-%d %H:%M:%S ",time.localtime())
        msg = now_time + msg

        self.msg_textedit.setFont(self.server_font)

        try:
            if msg_style == 0:
                self.msg_textedit.setStyleSheet('color:rgb(0,0,255)')
            else:
                self.msg_textedit.setStyleSheet('color:rgb(255,0,0)')

            self.msg_textedit.append(msg)
            '''设置QTextEdit自动滚屏'''
            self.msg_textedit.moveCursor(QTextCursor.End)
        except Exception as e:
            print("gprs_test_server_show_message exception!")
            traceback.print_exc()

    def gprs_test_server_btn_start(self):
        '''Start Button 响应'''
        server_port_str = self.server_port_edit.text()
        if server_port_str.isdigit() == False:
            print("illegal server port...")
            self.gprs_test_server_show_message('illegal server port!',1)
            return

        self.server_port_int = (int)(server_port_str)
        if self.server_port_int > 65535:
            self.gprs_test_server_show_message('illegal server port!',1)
            return

        self.gprs_test_server_init_work()
        '''进来之后将start button 置为不可用'''
        self.server_start.setEnabled(False)
        self.server_stop.setEnabled(True)
        self.server_port_edit.setEnabled(False)
        print("gprs_test_server_btn_start")
        self.gprs_test_server_show_message("Server Start....",0)
        self.server_thread.start()

    def gprs_test_server_btn_stop(self):
        '''Stop Button 响应'''
        self.server_port_edit.setEnabled(True)
        self.server_stop.setEnabled(False)
        self.server_start.setEnabled(True)
        print("gprs_test_server_btn_stop")
        self.gprs_test_server_show_message("Server Stop....",0)
        self.server_thread.quit()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = GprsTestServer()
    sys.exit(app.exec_())

猜你喜欢

转载自blog.csdn.net/yangkunhenry/article/details/100935319