4

Pharo 2.0 と Zinc Websocket を使用して、かなり大きなビデオ ファイルを Websocket 経由で送信しようとしています。これはファロからファロへの転送です。

私はこれを機能させるために無駄に試みました。私が見逃している非常に単純な解決策があると確信しています。助けてくれてありがとう。

編集:更新:次のコードを使用して、これを機能させました:

myStream :=   
(FileStream oldFileNamed: 'big_buck_bunny_480p_surround-fix.avi') .
bytes := myStream next: myStream size.
myStream close.
myStream := nil.
server distributeMessage: bytes.

testConnect
| websocket1 receivedFile|
websocket1 := ZnWebSocket to: 'ws://192.168.1.102:1701/ws-chatroom'.
testProcess := [ 
[ 
| mes |
mes := [ websocket1 readMessage ]
    on: ConnectionTimedOut
    do: [ nil ].
mes
    ifNotNil: [ 
        Transcript
            show: 'Message received in client';cr .
            receivedFile := FileStream newFileNamed: 'receivedFile3.avi'. 
receivedFile nextPutAll: mes.
receivedFile close.
             ] ] repeat ] fork

ただし、Pharo がメモリ不足になるため、500 メガバイトを超えるファイルでは機能しません。

誰かがこれを機能させるための優れた提案を持っていない限り、ギアを切り替えて、ZincHTTPComponents を使用してファイルを提供しようとします。おそらく、Web サーバーにダウンロードするファイルの場所を含むメッセージをリモート コンピューターに送信します。

編集: 重要な警告/更新:

この問題について、pharo smalltalk 用の Zinc Websocket パッケージを作成した Sven と話し合いました。彼は、websocket を介して大きなファイルを送信することは、実際には実行可能なアイデアではないと私に言いました。実際、以下のソリューションを実装しても、最終的なファイルは毎回数バイトずれていました。

計画 B: Zinc HTTP コンポーネントを使用して HTTP 経由でファイルを提供し、次のようなクライアント get を使用して、問題を解決しました。

FileStream 
    newFileNamed: '/tmp/cog.tgz' 
    do: [ :stream | | entity |
            stream binary.
            entity := ZnClient new
                    streaming: true;
                    get: 'https://ci.lille.inria.fr/pharo/job/Cog%20Git%20Tracker/lastSuccessfulBuild/artifact/cog.tar.gz';
                    entity.
            entity writeOn: fileStream ]
4

1 に答える 1

6

メモリが不足している理由は、ファイルを処理する前にファイル全体をメモリに読み込んでいるためです。とにかく、データのチャンクしか送信できないため、一度に 1 つのチャンクのみを読み取る必要があります (これがストリームの目的です)。したがって、これの代わりに:

myStream :=   
(FileStream oldFileNamed: 'big_buck_bunny_480p_surround-fix.avi').
bytes := myStream next: myStream size.
myStream close.

次のようなものを使用する必要があります。

blockSize := 128.
myStream :=   
(FileStream oldFileNamed: 'big_buck_bunny_480p_surround-fix.avi') .
[ myStream atEnd ] whileFalse: [
    bytes := myStream next: blockSize.
    "process your bytes here" ].
myStream close.

またはさらに良い: 便利なブロックを使用して、ストリームを自動的に閉じます。

blockSize := 128.  
FileStream 
    oldFileNamed: 'big_buck_bunny_480p_surround-fix.avi'
    do: [ :stream |
        [ stream atEnd ] whileFalse: [
            bytes := stream next: blockSize.
        "process your bytes here" ].

編集

コメントからの質問に答えるには:FileStream>>next:見ると、次の行が表示されます。

...
[self atEnd ifTrue:
    [(howManyRead + 1) to: anInteger do: [:i | newCollection at: i put: (self next)].
    ^newCollection].
...

これは、利用可能な以上のものを要求した場合、ストリームの残りを最後まで取得するだけであることを意味します。

于 2013-10-07T07:07:11.980 に答える