【问题标题】:Socket File Transfer sending incomplete files in C#套接字文件传输在 C# 中发送不完整的文件
【发布时间】:2012-01-26 10:30:57
【问题描述】:

我正在尝试使用 C# (.NET) 进行 Socket 编程。我参考了 codeproject 中的几个示例,但我的文件传输总是发送不完整的数据。

非常非常小的数据可以正常工作,例如 1kB。但较大的文件传输不完整,尤其是图像。

这是我的客户端代码,它将文件发送到服务器。 clientData 存储文件的二进制文件。

byte[] fileData = File.ReadAllBytes(filePath + fileName);
            byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
            byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);

            fileNameLen.CopyTo(clientData, 0);
            fileNameByte.CopyTo(clientData, 4);
            fileData.CopyTo(clientData, 4 + fileNameByte.Length);

            curMsg = "Connection to server ...";
            clientSock.Connect(ipEnd);
            int count;
            curMsg = "File sending...";
            count = clientSock.Send(clientData);
            MessageBox.Show(count+" "+clientData.Length);

            curMsg = "Disconnecting...";
            clientSock.Close();

虽然这是我用于接收文件的服务器的代码。

                sock.Listen(100);

            curMsg = "Running and waiting to receive file.";
            Socket clientSock = sock.Accept();

            byte[] clientData = new byte[1024 * 5000];

            int receivedBytesLen = clientSock.Receive(clientData);
            curMsg = "Receiving data...";

            int fileNameLen = BitConverter.ToInt32(clientData, 0);
            string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);

            BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath +"/"+ fileName, FileMode.Append)); ;
            bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);

            curMsg = "Saving file...";

            bWrite.Close();
            clientSock.Close();

有趣的是,当我在客户端的“发送”处设置断点时,文件可以正常传输。当我使用断点时,我正在观察两端的字节数和传输字节匹配,而当我不使用断点时,接收到的字节低于客户端传输的字节。

我做错了什么?

【问题讨论】:

  • 可以上传你写的分块发送数据的代码吗?
  • 您正在使用的 Close() 的重载不会等待发送/接收“完成”,您必须使用具有超时的重载,以便它有时间“清除”您的传出流。

标签: c# .net sockets tcpclient file-transfer


【解决方案1】:

您忘记实现协议了!要使用 TCP,您必须设计和实现一个协议,该协议定义将发送哪些字节以及接收方如何识别消息或协议数据元素。你什么都没做。您的接收代码无法知道它是否已接收到整个文件,因为没有协议可以告诉它,也没有任何代码可以实现这样的协议。所以它当然会出错——它没有办法让它正确。

如果 receivedBytesLen 为 1,您的代码将严重失败。

【讨论】:

  • 嗨,大卫。感谢您指出我正在使用以下代码来初始化套接字,我认为 ProtocolType.IP 会有所帮助。 ipEnd = new IPEndPoint(IPAddress.Any, 5656); sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); sock.Bind(ipEnd);
  • 我将 ProtocolType.Ip 更改为 ProtocolType.Tcp。仍然没有运气。我是绝对的初学者,请你具体一点。
  • 你根本没听懂我的回答。您正在尝试发送文件。 TCP 不是传输文件的协议,它是传输字节的协议。要传输文件,您需要一个协议来传输文件。在你写一行代码之前,你应该设计一个这样的协议并记录下​​来。
  • 对此感到抱歉 - 实际上这两个答案都让我解决了我的问题。你说的对。我没有让客户知道文件大小的协议。所以它适用于硬编码的字节长度。后来解决了这个问题。谢谢。
【解决方案2】:

底层网络或 TCP 层可能并不总是将整个文件作为一个单独的块发送。您可以尝试执行 while 循环,直到收到文件的确切/完整长度。

为此,您可能需要先发送文件的长度。

是的,这可能在调试模式下工作,但在运行时可能会有所不同。

【讨论】:

  • 感谢 Muthu,首先我尝试对文件大小进行硬编码。正确接收位。缓冲区被覆盖。
  • 是的,您需要将其附加到另一个字节数组或 List 并且在此之后不应覆盖。
猜你喜欢
  • 2014-10-18
  • 1970-01-01
  • 2015-05-16
  • 1970-01-01
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多