繁体   English   中英

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

[英]PHP to C# - Socket - File corrupts randomly

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

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

有时传输会随机损坏[图像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

此 stream 始终传输Bitmap图像 + 一些数据。


C#

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

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

当我检查不同的浏览器或浏览器的新实例时,它在最初的几次尝试中从未失败。

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

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

如果您查看 PHP socket_write 的文档,例如:

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

注意:socket_write() 返回零是完全有效的,这意味着没有写入任何字节。 如果出现错误,请务必使用 == 运算符检查 FALSE。

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

简单网络代码使用中最严重的缺陷之一是在发送文件数据之前没有发送文件的大小,因此接收方无法在发送响应之前知道要读取多少内容。 对于这样的简单操作,我建议只发送一个二进制 32 位 integer(4 个字节)。 这将是您的操作架构的一部分。 因此接收器将首先读取 4 个字节并从中知道需要读取多少字节(一次一个缓冲区大小)。 接收器一直读取,直到它们有那么多字节。

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

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

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

  1. 如果 '$cordinates' (sic) 是固定大小,则将其放在消息的前面,而不是后面
  2. 记录从 PHP 发送的大小和收到的大小。
  3. base64 在发送之前对二进制文件进行编码(并在接收端解码)

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM