Vigoss802 发表于 2022-10-12 23:31

python socket 服务程序求大助

需要用python 需要做一个获取几个设备状态数据的服务程序,本人小白熬了一个月,碰到线程实在搞不定,需要高手支持写个框架。万分感谢。


服务端需要创建两个socket
hostip = '192.168.123.456'
port1 = 12345
port2 = 67890

server1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server1.bind((hostip, port1))
server1.listen(2)   

server2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server2.bind((hostip, port1))
server2.listen(2)

# 这里server1 可收发数据,server2只接受数据


设备特性
设备启动后会主动connect端口1,server1.accept到后发送
<msg>
    <cmd>CONNECT</cmd>
    <data>
    </data>
</msg>
到设备,设备会反馈
<msg>
    <cmd>CONNECT</cmd>
    <data>
      <return>OK</return>
      <name>device_A</name>
    </data>
</msg>
且设备会同时会去connect端口2,server2.accept后可接受机床和上面一样的数据报告设备名称。
然后设备会反馈当前设备状态到server2.
<msg>
    <cmd>STATE</cmd>
    <data>
      <A>FALSE</A>
      <B>TRUE</B>
      <ERROR>FALSE</ERROR>
    </data>
</msg>

设备状态数据如果将来出现变化,会主动发给server2



服务端:
server1与设备的通讯是发一个反馈一个

<msg>
    <cmd>指令</cmd>
    <data>
    </data>
</msg>

<msg>
    <cmd>指令</cmd>
    <data>
      <return>OK</return>    #NOK
      ...                                    #......
    </data>
</msg>

server1需要每60秒发一个WATCHDOG指令给设备,确保设备没死机。
另外还有个server1还要根据设备某些状态发送特定指令给设备获取数据。
例如当状态<ERROR>TRUE</ERROR>时发送GETERRORS,机床反馈ok的同时会带错误列表。


这个服务器需要连接多个设备。 也需要支持设备重启后重连。







dork 发表于 2022-10-13 11:24

其实完全不用这个思路,换一个吧
flaskfastAPI都可以更好的实现你的要求。比你这C/S要好一些

wihn 发表于 2022-10-13 12:29

不要自己手写socket了,这样既麻烦,而且性能比不上众多大神写的\优化过的框架。这不是HTTP协议,因此我认为fastAPI这类框架不适用。可以看看SocketServer这个库,这是Python自带的,非底层的TCP框架。

littleworm 发表于 2022-10-13 13:07

关注一下可能也有同样需求

Vigoss802 发表于 2022-10-13 13:50

dork 发表于 2022-10-13 11:24
其实完全不用这个思路,换一个吧
flaskfastAPI都可以更好的实现你的要求。比你这C/S要好一些

设备是死的,所以没办法。

Vigoss802 发表于 2022-10-13 13:51

wihn 发表于 2022-10-13 12:29
不要自己手写socket了,这样既麻烦,而且性能比不上众多大神写的\优化过的框架。这不是HTTP协议,因此我认 ...

谢谢指点,有想过还是玩不转。

chr_233 发表于 2022-10-13 14:52

分享一个之前写的课设作业,这是main.py,使用select来异步建立socket连接和收发socket数据
然后由TCPHandler处理消息,之前用的是json,要用xml的话自己写就是了
另外感觉没必要开两个端口,消息可以用cmd区分类型,用一个socket足以

import select
import socket
import sys
from queue import Empty, Queue
from socket import socket as Socket

from core.tcp_handler import TCPHandler
from core.utils import log

LISTEN_ON = '0.0.0.0'

RECV_BYTES = 8192



def main(host, port):
    # Init TCP server
    tcp_socket = Socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_socket.setblocking(False)
    try:
      tcp_socket.bind((host, port))
      tcp_socket.listen(10)
      log(f'TCP server listening on {host}:{port}', None, False)
    except OSError as s:
      log(f'TCP server start error: {s}', None, True)
      return

    # Init TCPHandler
    tcp_handler = TCPHandler()

    log('Wating for clients ...', None, False)

    # Event loop
    try:
      inputs =
      outputs = []
      msg_queue = {}
      while True:

            rlist, wlist, elist = select.select(inputs, outputs, inputs, 1)
            for s in rlist:
                # any socket is ready for reading
                if s == tcp_socket:
                  # TCP incoming connection
                  conn, addr = s.accept()
                  conn.setblocking(False)

                  inputs.append(conn)
                  msg_queue = Queue()
                  # log('TCP connection established', addr, False)

                else:
                  data = s.recv(RECV_BYTES)
                  addr = s.getpeername()
                  if data:
                        # TCP message
                        response = tcp_handler.handle_message(data, addr)
                        msg_queue.put(response)
                        if s not in outputs:
                            outputs.append(s)
                  else:
                        # TCP close
                        # log('TCP connection closed', addr, True)
                        if s in outputs:
                            outputs.remove(s)
                        inputs.remove(s)
                        s.close()
                        msg_queue.pop(s, None)

            for s in wlist:
                # any socket is ready for writing
                try:
                  payload = msg_queue.get_nowait()
                  s.send(payload)
                  outputs.remove(s)
                  msg_queue.pop(s, None)
                except Empty:
                  pass

            for s in elist:
                # any socket raises error
                log('TCP connection error', None, True)

                inputs.remove(s)
                if s in outputs:
                  outputs.remove(s)

                msg_queue.pop(s, None)

                s.close()

    except KeyboardInterrupt:
      pass
    finally:
      tcp_socket.close()
      log('Server shutdown ...', None, True)


if __name__ == '__main__':

    try:
      port = int((sys.argv or ['12345']))
      if port < 0 or port > 65535:
            raise ValueError
    except ValueError:
      log('Usage: python3 server.py ', None, True)
      log('Default port is 12345', None, True)
      input('Press enter to exit...')
      exit(1)

    main(LISTEN_ON, port)



class TCPHandler():

    def handle_message(self, raw: bytes, addr: Tuple):
    try:
      response = None
      # addr = sock.getpeername()
      payload = json_deserializer(raw)
      # 这里处理消息
    except:
      pass

chr_233 发表于 2022-10-13 14:53

本帖最后由 chr_233 于 2022-10-13 14:58 编辑

chr_233 发表于 2022-10-13 14:52
分享一个之前写的课设作业,这是main.py,使用select来异步建立socket连接和收发socket数据
然后由TCPHand ...
完整源码是一个基于UDP的简单的论坛程序,没什么关联,就不放了



zsjalive 发表于 2022-10-13 15:54

chr_233 发表于 2022-10-13 14:53
完整源码是一个基于UDP的简单的论坛程序,没什么关联,就不放了
基于UDP的论坛程序源码能不能放出来,学习学习。

chr_233 发表于 2022-10-13 16:01

zsjalive 发表于 2022-10-13 15:54
基于UDP的论坛程序源码能不能放出来,学习学习。

课设而已,没什么实际用途
页: [1] 2
查看完整版本: python socket 服务程序求大助