pytohon에서 UNIX domain socket을 통해 openMSX에 연결

openMSX 외부 연결 socket에서 명령을 보낼 수 있기 때문에pythn을 사용하여 연결을 시도합니다.

컨디션

  • MacBook Air (13inch, Mid 2012)
  • macOS 10.15.7
  • python 3.9.4
  • 일의 전말


    python에서 UNIX domain socket으로 OpenMSX에 연결할 때 잘못된 노트를 시도합니다.
    만약 우여곡절이 있는 부분이 필요하지 않다면, "최종python 코드"를 참조하십시오.

    openMSX 브로셔


    openMSX의 설명서Controlling openMSX from Externam Application에서는 이렇습니다.
    There are multiple ways to connect to openMSX. The first (and oldest) way is using a pipe. On Windows you can use a named pipe, on other systems you use stdio. To enable this, start openMSX like this:
    openmsx -control stdio
    or for Windows:
    openmsx -control pipe
    The second method is using a socket. Connecting on non-Windows systems goes with a UNIX domain socket. openMSX puts the socket in/tmp/openmsx-/socket.. The/tmp/dir can be overridden by environment variables TMPDIR, TMP or TEMP (in that order).
    연결 방법은 두 가지가 있는데 하나는 파이프이고 다른 하나는 UNIX domain socket입니다.
    어쨌든 파이프로 연결하면 터미널에서 시험해 보면 쉽게 연결할 수 있다.
    paraches@uriel-2 MacOS % ./openmsx -control stdio
    <openmsx-output>
    <command>set renderer SDL</command>
    <reply result="ok">SDL</reply>
    <command>exit</command>
    <reply result="ok"></reply>
    </openmsx-output>
    paraches@uriel-2 MacOS % 
    
    다른 UNIX domain socket에 연결된 socket 파일은 다음과 같습니다.
    /tmp/openmsx-<username>/socket.<pid>
    
    이 연결을 사용하여python에서 socket 연결을 합니다.

    socket 파일 확인


    openMSX를 시작하여 socket 파일을 확인합니다.
    paraches@uriel-2 /tmp % ls -l
    total 0
    drwx------  4 root      wheel  128  2 11 12:55 PKInstallSandbox.dLsXw9
    drwx------  3 paraches  wheel   96  4 13 22:29 com.apple.launchd.TQ8qbaX0ky
    drwx------  3 paraches  wheel   96  4 13 22:29 com.apple.launchd.c930VoZ6Cr
    drwxr-xr-x  5 paraches  wheel  160  4 13 23:47 openmsx.921
    drwxr-xr-x  2 root      wheel   64  4 13 22:29 powerlog
    paraches@uriel-2 /tmp % ls
    
    /tmp 폴더에 Openmsx- 같은 폴더가 없습니다. Openmx.<서류철에는 무슨 뜻인지 모르는 서류가 세 개밖에 없다.socket.<어디에도pid>이 파일이 없습니다.

    나는 잠시 모르는 세 개의 파일을 socket 파일로 연결하기로 결정했다.

    개인 코드

    python unix domain socket에서 검색하면 많이 나오지만 이번에는 클라이언트 코드가 필요합니다.많이 확인하고 이런 코드를 준비했어요.
    import socket
    
    def connect(path):
        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        s.connect(path)
        data = s.recv(1024)
        print('recieve: %s' % data.decode())
        s.close()
    
    def main():
        connect('/tmp/openmsx.921/Bvq4ew')
    
    if __name__ == '__main__':
        main()
    
    socket 파일의 경로는 앞에 열거한 세 파일에서 각각 시험해 보았지만, 결과는 socket 파일과 같은 오류가 아니었습니다.
    paraches@uriel-2 openMSX_socket % python psocket.py
    <中略>
    socket.error: [Errno 38] Socket operation on non-socket
    paraches@uriel-2 openMSX_socket % 
    
    그럼, 수고하세요.

    openMSX Debugger


    OpenMSX Debugger를 사용하면 OpenMSX와 socket에 연결될 존재가 생각납니다.이 코드를 읽으면 socket 파일의 위치를 알 수 있지 않을까요?
    이에 따라 지난 글'MacOS로 openMSX Debugger 구축의 우여곡절을 통해 오픈MSX 디버그가 오픈MSX와 연결될 수 있음을 확인했다.코드를 읽다.

    ConnectDialog.cpp


    openMSX Debugger의 소스ConnectDialog.cpp에서 checkSocket 함수를 발견했습니다.매개 변수 QFileInfo 의 파일 이름은 "socket."입니다.확인을 시작하겠습니다.
    즉, socket 파일은 설명서의 socket입니다.로 정답입니다.
    그럼 이 서류는 어디에 있습니까?checkSocket 함수를 수정하여 디버깅 출력absoluteFilePath()으로 시작합니다.
    ConnectDialog.cpp
    qDebug() << info.absoluteFilePath();
    
    openMSX Debugger의 connect 대화 상자에서 Rescan을 호출하면 socket 파일의 위치가 표시됩니다.
    paraches@uriel-2 MacOS % ./openmsx-debugger
    "/var/folders/6v/cq3c0g0j4214dbg338snk5pr0000gn/T/openmsx-paraches/socket.2271"
    
    마닐라의openmsx- 폴더에 있는 socket. 파일이 있습니다.
    맞다/var/folders가 뭐예요?

    /var/folders


    /var은 일시적인 파일 배치 장소로 식별되지만, 맥OS는 folders를 왜 사용합니까?
    찾아보니 애플리케이션의 캐시 사용인 것 같습니다.
    https://ascii.jp/elem/000/001/123/1123733/2/
    즉시 자신의 기계에서 환경 변수를 확인하세요.
    paraches@uriel-2 MacOS % echo $TMPDIR
    /var/folders/6v/cq3c0g0j4214dbg338snk5pr0000gn/T/
    paraches@uriel-2 MacOS % 
    
    openmsx- 폴더의 경로를 표시합니다.
    마침내 알아차렸다.
    최초의 수첩에는... 이라고 쓰여 있다.
    The/tmp/dir can be overridden by environment variables TMPDIR, TMP or TEMP (in that order).

    마지막python 코드


    socket 파일이 $TMPDIR 아래에 있는 것을 발견하여python 코드를 변경했습니다.os.getenv('TMPDIR') 소켓 파일을 찾습니다.
    마지막 코드는 이거예요.
    psocket.py
    import os
    import sys
    import socket
    import getpass
    from pathlib import Path
    
    
    class SocketClient:
        def __init__(self, path):
            self.socket_path = path
            self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    
        def connect(self):
            self.socket.connect(self.socket_path)
            self.receive_data()
    
        def disconnect(self):
            self.socket.close()
    
        def send_message(self, message):
            self.socket.send(message.encode())
            self.receive_data()
    
        def receive_data(self):
            data = self.socket.recv(1024)
            print('receive: %s' % data.decode())
    
    
    def find_socket_files():
        tmp_dir = Path(os.getenv('TMPDIR'))
        socket_dir = tmp_dir / ('openmsx-%s' % getpass.getuser())
        socket_files = socket_dir.glob('socket.*')
        return [str(s_file) for s_file in socket_files]
    
    def main():
        socket_files = find_socket_files()
        if len(socket_files) > 0:
            client = SocketClient(socket_files[0])
            client.connect()
            client.send_message("<command>exit</command>")
            client.disconnect()
    
    if __name__ == '__main__':
        main()
    
    이렇게 지령을 보내면... 연결 성공!
    paraches@uriel-2 ~ % python psocket.py
    receive from server: <openmsx-output>
    
    receive from server: <reply result="ok"></reply>
    
    paraches@uriel-2 ~ % 
    
    openMSX가 순조롭게 끝났다.

    교훈.


    이번 교훈은 이거야.
    사용 방법은 경솔하게 단정하지 말고 끝까지 진지하게 읽어야 한다.
    "네,/tmp에 socket 파일이 있어요."라고 경솔하게 단정하면 행동이 이상해집니다.분명히 그 전에도 안 그랬던 적이 있었는데...
    지난번과 이번에는pytohon에서 OpenMSX를 제어할 수 있지만, 지난번 OpenMSX Debugger를 사용하면 하고 싶은 일을 모두 할 수 있을 것 같아서 일부러 pytohon에서 제어할 필요가 없습니다.

    좋은 웹페이지 즐겨찾기