PHP到c# -套接字-文件随机损坏

本文关键字:随机 损坏 文件 套接字 PHP | 更新日期: 2023-09-27 18:02:50

我有一个TCP连接,其中客户端是PHP,服务器是C#

此套接字连接传输图像socket服务器,但是

随机有时传输损坏[image hash不同]

PHP客户机

$file = file_get_contents('img.bmp');
socket_write($socket,$file.$cordinates); it sends //image + sme other data
$recv = socket_read ($socket, 500, PHP_BINARY_READ) // read the server response

这个流总是传输一个位图图像+一些数据。


c#

 this.DataSocket = this.Listner.Accept();
int filelength = this.DataSocket.Receive(this.buffer, this.buffer.Length, SocketFlags.None)

我调查了在fresh-browser[新打开的]中,这从来没有失败过。但当我使用这个创建的服务多次频繁在同一个浏览器,这打算失败。

当我用不同的浏览器新的浏览器实例检查时,从来没有前几次尝试中失败。

我认为这是caching的一些问题,但我禁用caching使用headers,但同样的问题存在

PHP到c# -套接字-文件随机损坏

您不能简单地期望一次将整个文件写入套接字,也不能期望在一次操作中从套接字读取文件。从BSD套接字到WinSock再到。net网络类,几乎所有网络编程API的套接字读写API都将发送或接收数据,直到所需的字节数。

如果你看一下PHP的socket_write文档,例如:

返回成功写入套接字的字节数,如果失败则返回FALSE。可以使用socket_last_error()检索错误代码。此代码可以传递给socket_strerror()以获得错误的文本解释。

注意:socket_write()返回零是完全有效的,这意味着没有写入字节。在出现错误时,请确保使用==操作符检查是否为FALSE。

你通常想要选择一个像4096或16384这样的块大小,并循环发送或接收该块大小,直到你得到所需的发送或接收字节数。你的代码必须检查你调用的发送或接收函数的返回值,并相应地调整你的文件指针。如果transmit返回0,这可能只是意味着发送缓冲区已满(不是致命的),所以继续发送(可能需要一个Sleep(0)延迟)。如果receive返回0,这通常意味着另一方已经干净地关闭了连接。

在你的简单网络代码使用中最关键的缺陷之一是你在发送文件数据之前没有发送文件的大小,所以接收方在发送响应之前没有办法知道要读多少。对于这样一个简单的操作,我建议只发送一个二进制32位整数(4字节)。这将是操作模式的一部分。因此,接收器将首先读取4个字节,并从中知道需要读取多少字节(一次一个缓冲区大小)。接收方继续读取,直到有足够的字节为止。

我希望这对你有帮助。如果套接字代码像您尝试的用法一样简单,那就太好了,但不幸的是,事实并非如此。你必须选择一个缓冲区大小,然后一直读写这个大小的缓冲区,直到你得到你想要的,你必须向另一方传达你计划发送多少数据。

你认为缓存与问题有任何关系,这意味着要么在你发布的代码之外有很多影响结果的功能,要么你离理解问题还有很长的路要走。

在不知道bmp文件结构的情况下,我首先关心的是如何将文件与发送的附加信息分开。有几件事你可以试试…

  1. 如果'$ coordinates ' (sic)是一个固定的大小,那么把它放在消息的前面,而不是后面
  2. 记录从PHP发送和接收的大小。
  3. base64在二进制文件发送前进行编码(并在接收端解码)

以上解决方案都不适合我,但我发现每次在一个请求后创建一个新实例将解决问题。但我不认为这是一个可靠的方法。

我尝试使用ASP.NET客户端,但结果相同。我认为这不是客户端PHP的问题,这肯定是套接字服务器的问题