博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
socket 实现单一串口共享读写操作
阅读量:5024 次
发布时间:2019-06-12

本文共 10407 字,大约阅读时间需要 34 分钟。

前提:物理串口连接到PC上,通过串口号被PC唯一识别。

此时,物理串口通过该串口号仅能被单一线程或进程实例并占用,

其他线程或进程不能再通过该串口号与物理串口通信。这个暂称为串口独占性。

解决思路:

核心思想:利用计算机软件中的socket编程,一个socket server 可以连接多个socket client,由socket server 完成多个socket client与物理串口的通信。

实现过程:

1、编程语言根据物理串口的串口号实例化一个串口操作类,串口操作类负责与物理串口通信。建立串口写线程和串口读线程。其中,串口读线程不断收取物理串口输出,并存放到读缓存。串口写线程不断从写缓存取命令,由其不断发往物理串口。
2、建立一个可靠的Socket Server,当有Socket Client连接时,由其将读缓存中的数据发给Socket Client,并不断收取Socket Client发来的命令,存放到写缓存中。
3、编程语言线程/进程通过建立Socket Client连接到Socket Server,既可实现多个线程/进程
与物理串口的通信

 

以下没有实现缓存机制,而是将读取到的串口数据放入队列:

socket server

#!/usr/bin/python# -*- coding: utf-8 -*-import socketimport psutilimport tracebackimport threadingimport SocketServer import jsonimport sysimport Queueimport timefrom serial import Serialfrom SocketServer import StreamRequestHandler as SRHfrom CustomStringIO import  CustomStringIOSERIALCOMNUM = {}class MainHandler(SRH):        def handle(self):        try:            print 'Client [%s] is Connected To The Server On Port [%s].' % (self.client_address[0], self.client_address[1])            self.keep_alive = True            while self.keep_alive:                data = self.request.recv(4096 * 3)                if not data:                    break                data_json = json.loads(data)                if "RequestType" in data_json:                    if data_json["RequestType"] == "DevSerialHandle":                        if "Port" in data_json["Args"]:                            self.dev_serial_handler(data_json, close_timeout=60)                            break                else:                    break        except Exception as e:            traceback.print_exc()        finally:          print '<------ SerialSocketServer handle request finish ------>'    def dev_serial_handler(self, data_json, close_timeout=60):        self.read_queue = Queue.Queue()        read_id = str(time.time())        if data_json["Args"]['Port'] in SERIALCOMNUM:            self.dev_serial = SERIALCOMNUM[data_json["Args"]["Port"]]['serial']            self.dev_serial.client_buffer.update({read_id:self.read_queue})            SERIALCOMNUM[data_json["Args"]["Port"]]['count'] += 1        else:            self.dev_serial = SerialHandle(data_json["Args"]['Port'])            self.dev_serial.client_buffer.update({read_id:self.read_queue})            SERIALCOMNUM.update({data_json["Args"]['Port']:{'serial':self.dev_serial,'count':1}})        print str(SERIALCOMNUM)        th_dev_serial_read = threading.Thread(target=self.read_dev_serial)        th_dev_serial_read.start()                is_recv_data_none = False        while self.keep_alive:            try:                data = self.request.recv(4096 * 3)                print 'your input is %s' % str(data)            except socket.error:                self.keep_alive = False                print "close dut serial"                break            else:                 if data:                    self.dev_serial.write(data)                    end_time = time.time() + close_timeout                # socket client 关闭后,self.request.recv会一直收到空字符串,等待一段时间后,关闭连接                else:                    if is_recv_data_none == False:                        is_recv_data_none = True                        end_time = time.time() + close_timeout                    if time.time() > end_time:                        print 'wait for webbroswer connect timeout'                        print "close dut serial"                        self.keep_alive = False                        break        if SERIALCOMNUM[data_json["Args"]["Port"]]['count'] > 0:            SERIALCOMNUM[data_json["Args"]["Port"]]['count'] -= 1            SERIALCOMNUM[data_json["Args"]["Port"]]['serial'].client_buffer.pop(read_id)        print str(SERIALCOMNUM)        if SERIALCOMNUM[data_json["Args"]["Port"]]['count'] <= 0:            print 'clear serial start'            SERIALCOMNUM[data_json["Args"]["Port"]]['serial'].close()            if data_json["Args"]['Port'] in SERIALCOMNUM:                SERIALCOMNUM.pop(data_json["Args"]["Port"])            def read_dev_serial(self):        try:            while self.keep_alive:                # serial_log = self.dev_serial.read()                serial_log = self.read_queue.get()                self.request.send(serial_log)        except socket.error:            passclass ThreadingServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):    def _threading_server(self):        passclass SerialSocketServer(object):    def __init__(self, port=33233):        self.server = None        self.port = 33233    def start(self):        netcard_ips = self.get_netcard()        for netcard_ip in netcard_ips:            host = netcard_ip[1]            try:                port = self.port                addr = (host, port)                self.server = ThreadingServer(addr, MainHandler)                self.server.allow_resuse_address = True                server_thread = threading.Thread(target=self.server.serve_forever)                server_thread.daemon = True                server_thread.start()                print "Starting Serial Socket Successfully!"                while True:                    try:                        INPUT = raw_input()                    except KeyboardInterrupt:                        sys.exit(0)                        break                    except EOFError:                        print 'Unknown End of file!'                        continue            except Exception, e:                print "Starting Serial Socket Server Fail:%s" % e    def stop(self):        print "Shutdown Slave Socket Server!"        if self.server != None:            self.server.shutdown()            self.server.server_close()    def get_netcard(self):        """获取网卡信息和ip地址        """        netcard_info = []        info = psutil.net_if_addrs()        for k, v in info.items():            for item in v:                if item[0] == 2 and not (item[1] == '127.0.0.1' or item[1] == '192.168.2.201'):                    netcard_info.append((k, item[1]))        return netcard_infoclass SerialHandle():    def __init__(self, port=None, baudrate=115200, timeout=30, *args, **kargs):        self.serial = Serial(port=port, baudrate=baudrate, timeout=timeout, *args, **kargs)        self.is_running = True        self.read_buffer = ""        self.write_queue = Queue.Queue()        self.read_buffer = CustomStringIO(4096)        th_wt = threading.Thread(target=self.__write)        th_wt.start()        th_rd = threading.Thread(target=self.__read)        th_rd.start()        self.client_buffer = {}    def read(self, read_id):        return self.read_buffer.getvalue()    def __read(self):        while self.is_running:            serial_log = self.serial.readline()            for key, value in self.client_buffer.items():                self.client_buffer[key].put(serial_log)           def write(self,write_string):        self.write_queue.put(write_string)    def __write(self):        while self.is_running:            write_string = self.write_queue.get()            self.serial.write(write_string)    def close(self):        self.is_running = False        self.serial.close()        print 'close serial'if __name__ == '__main__':    SerialSocketServer().start()

启动服务器:python serial_socket_server.py

socket client :

import threadingimport socketimport tracebackimport jsonimport sysimport reimport Queueclass DevSerialLoadClient(threading.Thread):    def __init__(self, node_ip, server_port=33233, serial_port="COM19"):        threading.Thread.__init__(self)        self.slave_serial_serial_server = node_ip        self.server_port = server_port        self.serial_port = serial_port        self.bufsize = 4096 * 4        self.setDaemon(True)        self._is_running = True        self._is_establish_connection = False        self.client = None    def connect(self):        try:            addr = (self.slave_serial_serial_server, self.server_port)            self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)            self.client.connect(addr)            self._is_establish_connection = True        except Exception as e:            self._is_establish_connection = False            print "Create Socket Connect Fail: %s" % e    def run(self):        self.connect()        if self.is_establish_connection:            request_msg = json.dumps({"RequestType":"DevSerialHandle","Args":{"Port":self.serial_port}})            self.client.send(request_msg)                      while self._is_running:                try:                    response = self.client.recv(self.bufsize)                    if not response:                        continue                    handle_response = re.compile('[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f|\\xff]').sub(' ', response.decode('unicode-escape'))                    print '%s' % str(handle_response)                except socket.error:                    print 'socket error'                    self.connect()                except:                    traceback.print_exc()            print "------stop dev serial communication------"            self.close()             def close(self):        try:            if self.client:                self.client.shutdown(socket.SHUT_RDWR)                self.client.close()        except Exception, e:            print "close socket client Error[%s]" % str(e)    @property    def is_establish_connection(self):        return self._is_establish_connection    def stop(self):        self._is_running = Falseif __name__ == '__main__':    import getopt    opts, args = getopt.getopt(sys.argv[1:], "h:s:")    server_ip = "localhost"    server_port = 33233    serial_port = None    for op, value in opts:        if op == "-h":            server_ip = value        if op == '-s':            serial_port = value    if not serial_port:        print 'should provide serial port args: like -p COM19'    dev_serial = DevSerialLoadClient(node_ip=server_ip, server_port=server_port, serial_port=serial_port)    dev_serial.start()    while True:        try:            INPUT = raw_input()            dev_serial.client.send(INPUT+'\n')        except KeyboardInterrupt:            sys.exit(0)            break        except EOFError:            print 'Unknown End of file!'            continue

 启动socket client:python serial_socket_client.py -h 对端ip -s 串口号

在命令行可向要连接的串口发送指令。

可建立多个client读写同一串口,所有client都可向串口发送数据;当一个client向串口输入数据后,其他client都可以收到串口的打印

转载于:https://www.cnblogs.com/linyihai/p/7071538.html

你可能感兴趣的文章
盒子模型
查看>>
局域网协议
查看>>
[HNOI2012]永无乡 线段树合并
查看>>
Spring整合hibernate:3、使用XML进行声明式的事务管理
查看>>
SqlServer之Convert 函数应用格式化日期(转)
查看>>
软件测试领域中的10个生存和发展技巧
查看>>
Camera前后摄像头同时预览
查看>>
HDU 1856
查看>>
课堂作业01--架构师的职责
查看>>
iOS计算富文本(NSMutableAttributedString)高度
查看>>
2017/09/15 ( 框架2)
查看>>
SpringMVC(十六) 处理模型数据之SessionAttributes
查看>>
阅读笔记01
查看>>
mysql设置有外键的主键自增及其他
查看>>
laravel常用函数大全Helper
查看>>
poj2299 Ultra-QuickSort
查看>>
第三部分shell编程3(shell脚本2)
查看>>
一个基于jQuery的移动端条件选择查询插件(原创)
查看>>
C# Winform 自适应
查看>>
IE阻止个别AC插件的原因及解决办法
查看>>