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

使用pharo 2.0中的pharo、ZnWebsocket和Fuel通过websocket发送文件?,websocket,smalltalk,pharo,Websocket,Smalltalk,Pharo,我正在尝试使用Pharo 2.0和Zn websocket通过websocket发送相当大的视频文件。这是航标到航标的转机 我试图让这件事起作用,但徒劳无功。我肯定我缺少一个非常简单的解决方案。谢谢你的帮助 编辑:更新:我确实通过以下代码实现了这一点: myStream := (FileStream oldFileNamed: 'big_buck_bunny_480p_surround-fix.avi') . bytes := myStream next: myStream size. m

我正在尝试使用Pharo 2.0和Zn 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
但是,它不适用于大于~500 MB的文件,因为Pharo内存不足

除非有人有很好的建议让它工作,否则我将切换设备,尝试使用ZincHTTPComponents为文件提供服务,并可能向远程计算机发送一条消息,其中包含要在Web服务器上下载的文件的位置

编辑:重要警告/更新:

我与Sven讨论了这个问题,他为pharo smalltalk编写了锌websocket软件包。他告诉我,通过websocket发送大文件并不是一个切实可行的想法。事实上,即使我实现了下面的解决方案,最终文件每次都会减少几个字节

我通过执行计划B解决了我的问题:使用ZINK 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 ]

内存不足的原因是在处理之前将整个文件读入内存。由于您无论如何只能通过线路发送数据块,因此您也应该一次只读取一个数据块(这就是流的用途)。因此,与此相反:

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>>下一步:
,您将看到以下几行:

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

这意味着,如果您要求的内容超过了可用的内容,您只需将流的其余部分一直保留到流的末尾。

到底有什么不起作用?您是否嗅探了目标计算机上的流量以查看数据包是否进入?包出去了吗?你试过没有websocket吗?我想不出通过websocket频道以二进制方式发送文件的代码。我可以很好地发送和接收字符串。将
#binary
发送到流通常可以做到这一点。当到达文件末尾且最终数据包不是128个完整块大小时,是否存在可能的问题?@zensches我在回答中的注释中包含了您问题的答案。