我们要求将大型固件文件上传到打印机以升级设备的固件。打印机设备与我的服务器位于同一网络中,我们尝试上传的固件大小约为200 - 500 MB。我们选择的方法是将固件(.bin文件)加载到内存流中,然后使用TcpClient
通过网络以块的形式写入。
根据网络流的响应,我们正在向客户端显示固件升级的状态。以下是我们用于固件升级的代码段。我想知道它是否是最佳方法,因为错误的方法可能会损坏设备。
修改
class MyClass
{
int port = 9100;
string _deviceip;
byte[] m_ReadBuffer = null;
TcpClient _tcpclient;
NetworkStream m_NetworkStream;
static string CRLF = "\r\n";
public event EventHandler<DeviceStatus> onReceiveUpdate;
public async Task<bool> UploadFirmware(Stream _stream)
{
bool success = false;
try
{
_tcpclient = new TcpClient();
_tcpclient.Connect(_deviceip, port);
_stream.Seek(0, SeekOrigin.Begin);
m_NetworkStream = _tcpclient.GetStream();
byte[] buffer = new byte[1024];
m_ReadBuffer = new byte[1024];
int readcount = 0;
m_NetworkStream.BeginRead(m_ReadBuffer, 0, m_ReadBuffer.Length,
new AsyncCallback(EndReceive), null);
await Task.Run(() =>
{
while ((readcount = _stream.Read(buffer, 0, buffer.Length)) > 0)
{
m_NetworkStream.Write(buffer, 0, readcount);
m_NetworkStream.Flush();
}
});
success = true;
}
catch (Exception ex)
{
upgradeStatus = false;
}
return success;
}
private void EndReceive(IAsyncResult ar)
{
try
{
int nBytes;
nBytes = m_NetworkStream.EndRead(ar);
if (nBytes > 0)
{
string res = Encoding.UTF8.GetString(m_ReadBuffer, 0, nBytes);
DeviceStatus status = new DeviceStatus();
string[] readlines = res.Split(new string[] { CRLF },
StringSplitOptions.RemoveEmptyEntries);
foreach (string readline in readlines)
{
if (readline.StartsWith("CODE"))
{
//read readline string here
break;
}
}
}
if (m_NetworkStream.CanRead)
{
do
{
m_NetworkStream.BeginRead(m_ReadBuffer, 0, m_ReadBuffer.Length, new
AsyncCallback(EndReceive), null);
} while (m_NetworkStream.DataAvailable);
}
}
catch (ObjectDisposedException ods)
{
return;
}
catch (System.IO.IOException ex)
{
}
}
}
任何帮助都将非常感激。
答案 0 :(得分:2)
您的代码基本上没有问题:
m_NetworkStream.Flush();
AFAIK这没有任何作用。如果它做了某些事情会损害吞吐量。所以删除它。_stream.Seek(0, SeekOrigin.Begin);
寻求是来电者的关注,删除它。这是一个分层违规。Stream.Copy
替换整个读写循环。using
以确保在错误情况下清除它们。nBytes = m_NetworkStream.EndRead(ar);
在这里,您假设单个读取将返回将要发送的所有数据。但是,您可能只收到第一个字节。可能,您应该在循环中使用StreamReader.ReadLine
,直到您知道自己已完成为止。catch (System.IO.IOException ex) { }
那是什么意思?如果固件更新是如此重要的事情,抑制错误似乎非常危险。你怎么能找到有关错误的内容?await
。答案 1 :(得分:-2)
由于TcpPacket的最大长度为65535(2 ^ 16-1),如果发送任何超出此长度的数据包,它将被截断。如果我是你,我认为发送大数据包的最佳方法是设置每个数据包的Header并枚举它们。例如:
C-> S; [P1] <content>
然后是相同的结构,只加1 [P2] <content>
为此,只需使用少量子串截断数据并发送它们。
干杯!