socat:シェルを使用して簡単な二重通信を実行するには?

socat:シェルを使用して簡単な二重通信を実行するには?

リモートサーバーへのTCP接続を作成し、socatクライアントが送信します。

  1. 画像ファイルの操作("convert""open"など)
  2. イメージ(バイナリコンテンツ)自体

その後、サーバーは与えられたタスクを使用して画像を処理します。

私の最初の考えは、バイナリコンテンツの前にこのテキスト操作タイプを渡すことでした。

# client
socat tcp:server:9999 -\
  < <(echo "open"; cat path/to/imgfile)

# server
socat tcp-listen:9999 - | {
  IFS= read -r action
  cat - > /tmp/imgfile
  # do process image file with action type ...
}

これは特定の状況では機能しているように見えますが、複数のパラメータを渡す必要がある場合など、柔軟ではありません。また、バイナリコンテンツの前にテキストを追加すると、画像ファイルが破損している可能性があります。

だから私は2つのパラメータを1つずつ渡すよりきれいな解決策を見つけようとしました(ここでは二重通信と呼ばれます)。

ここに画像の説明を入力してください。

これまで私が試したことは、次の分野の専門家ではないということですsocat

# client
socat\
  tcp:server:9999\
  system:'echo "open"; IFS= read -r ack; cat path/to/image.png'

# server
socat tcp-listen:9999\
  system:'IFS= read -r action; echo "ACK"; binary=$(cat -); echo "process image with action now..."'

今は許してください

壊れたパイプ

このタイプの二重通信は可能ですかsocat(新しいポートを開かない最良の場合)。

より簡単な選択肢を考えてみましたか?

おそらくこれはもはやフレームを使用せず、可能であればHTTPサーバーのオーバーヘッドなしで最も簡単で簡単な方法で行う必要があると言いたいと思います。シェルはBashであり、利用可能なZSHはありません。一般的なPythonを使用できます。

ベストアンサー1

socatを使用してこのタイプの二重通信が可能ですか(新しいポートを開かない最良の場合)。

いいえ。しかし、それはそれとは何の関係もありませんsocat。 TCP接続が閉じられ、使用できなくなりました。しかし、特にcat -Stéphaneが指摘したように、あなたのメカニズムは接続を閉じることに依存しています。

シェルはBashであり、利用可能なZSHはありません。一般的なPythonを使用できます。

だから、普通のPythonです。

~から 含まれるモジュールのPythonドキュメント、実際にはわずかに修正されました。

from xmlrpc.server import SimpleXMLRPCServer
from xmlrpc.server import SimpleXMLRPCRequestHandler

PORT = 8000

class RequestHandler(SimpleXMLRPCRequestHandler):
    rpc_paths = ('/RPC2',)

with SimpleXMLRPCServer(('localhost', PORT),
                        requestHandler = RequestHandler,
                        use_builtin_types = True) as server:
    server.register_introspection_functions()

    # Register a function under function.__name__.
    @server.register_function
    def convert(target_format: str, img: bytes):
        # do something with img instead of just returning it,
        # but you get the idea.
        return img

    @server.register_function
    def length(img: bytes):
        return len(img)


    server.serve_forever()

クライアント側では

import xmlrpc.client

PORT = 8000

server_handle = xmlrpc.client.ServerProxy(f'http://localhost:{PORT:d}',
                                          use_builtin_types = True)

with open("inputimage.jpg", "rb") as infile:
    converted = server_handle.convert("image/png", infile.read())

with open("outputimage.png", "wb") as outfile:
    outfile.write(converted)

# Print list of available methods
print(server_handle.system.listMethods())

これは確かに一般的なPythonであることに注意してください。xmlrpc.server標準のPythonにはそれ以上もsocket含まれていませんmath


ここからバニラの概念を拡張できます。venvこれはPython標準ライブラリの一部でもあります。あなたは本当に良いと思います。持つ標準のPythonです。

python3 -m venv serverstuff
. serverstuff/bin/activate
pip install Flask

もう少し快適にしてください。その後、次のようなサーバーを作成できます。クイックスタートの例:

from flask import Flask
from flask import request
from flask import Response

app = Flask(__name__)


@app.route("/")
def say_hello():
    return "helloo"


@app.route("/convert/<target_fmt>"):
def convert(target_fmt):
    print(target_fmt)
    try:
        infile = request.files["file"]
    except Exception as e:
        print(e)
        return Response(response="", status=406)
    # convert it; infile is a Werkzeug.Filestorage
    # https://werkzeug.palletsprojects.com/en/2.3.x/datastructures/#werkzeug.datastructures.FileStorage
    data = infile.read()
    return Response(response=data, mimetype=f"image/{target_fmt}", status=200)

として保存server.pyして実行しますpython3 -m flask --app server run --port 8000

これにより、クライアント側のシェルスクリプトが非常に簡単になります。

$ myfiletoupload=/home/mosaic/catpicture.jpg
$ curl http://127.0.0.1:8000/convert/png -F "file=@${myfiletoupload}"

おすすめ記事