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

时间:2011-07-18 04:58:54

标签: c# php sockets tcp

我有一个 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

此流始终传输位图图像+一些数据。


C#

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

我调查过,在新浏览器 [新开启]这种情况从未失败过。但是当我在同一个浏览器中使用此创建的服务多次时,这意味着失败。

当我使用浏览器的其他浏览器新实例进行检查时,从不前几中失败尝试。

我认为caching存在问题,但我使用caching禁用了headers,但存在同样的问题

3 个答案:

答案 0 :(得分:10)

您不能简单地期望立即将整个文件写入套接字,也不能期望在一次操作中从套接字读取文件。从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个字节,并从中知道需要读取多少字节(一次一个缓冲区大小)。接收器继续读取,直到它们有那么多字节。

我希望这会有所帮助。如果套接字代码与您尝试的用法一样简单,那将是很好的,但不幸的是,它不是。你必须选择一个缓冲区大小,然后继续读取或写入那个大小的缓冲区,直到你得到你想要的东西,你必须向另一方传达你计划发送多少数据。

答案 1 :(得分:2)

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

在不知道bmp文件结构的情况下,我首先要关注的是如何将文件与发送的其他信息分开。你可以尝试一些事情......

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

答案 2 :(得分:0)

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

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