使用pharo,ZnWebsocket和Pharo 2.0中的Fuel通过websocket发送文件?

zen*_*ess 4 smalltalk pharo websocket

我试图使用Pharo 2.0和Zinc Websocket在websocket上发送相当大的视频文件.这是一个pharo到pharo转移.

我试图让这个工作起来是徒劳的.我确信我有一个非常简单的解决方案.谢谢你的帮助.

编辑:更新:我确实通过以下代码使其工作:

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
Run Code Online (Sandbox Code Playgroud)

但是,它不适用于大于500兆字节的文件,因为Pharo内存不足.

除非有人有一个很好的建议让这个工作,我将切换齿轮并尝试使用ZincHTTPComponents提供文件,并可能向远程计算机发送一条消息,其中包含要在网络服务器上下载的文件的位置.

编辑: 重要警告 /更新:

我和Sven一起讨论了这个问题,他为pharo smalltalk编写了Zinc websocket包.他告诉我,在websocket上发送大文件并不是一个可行的想法.实际上,即使我得到了下面实现的解决方案,最终文件每次都会关闭几个字节.

我通过执行我的计划B解决了我的问题:使用Zinc HTTP Components通过HTTP提供文件并使用客户端获取如下:

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 ]
Run Code Online (Sandbox Code Playgroud)

Max*_*ske 6

内存不足的原因是在处理之前将整个文件读入内存.由于您无论如何只能通过网络发送数据块,因此您也应该一次只读取一个数据块(这就是流的目的).所以不是这样的:

myStream :=   
(FileStream oldFileNamed: 'big_buck_bunny_480p_surround-fix.avi').
bytes := myStream next: myStream size.
myStream close.
Run Code Online (Sandbox Code Playgroud)

你应该使用这样的东西:

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.
Run Code Online (Sandbox Code Playgroud)

甚至更好:使用便利块自动关闭流:

blockSize := 128.  
FileStream 
    oldFileNamed: 'big_buck_bunny_480p_surround-fix.avi'
    do: [ :stream |
        [ stream atEnd ] whileFalse: [
            bytes := stream next: blockSize.
        "process your bytes here" ].
Run Code Online (Sandbox Code Playgroud)

编辑

要回答你的评论中的问题:如果你看,FileStream>>next:你会看到以下几行:

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

这意味着如果您要求的数量超过可用数量,您只需将流的其余部分直到最后.