如何确保流被完全读取
本文关键字:读取 何确保 确保 | 更新日期: 2023-09-27 18:20:23
我正在使用Network Stream, TcpListener and Sockets
。
我想确保来自发送者的所有数据都被接收者接收到。
我有接收器的以下代码
private void StartReciever()
{
util.LoadSettings();
string tcpIpAddress = util.svrSettings["IpAddress"];
string port = util.svrSettings["Port"];
string outDir = util.svrSettings["isOutput"];
new Thread(
() =>
{
if (!File.Exists(util.settingFile))
Logger("Please setup the services first.");
else
{
try
{
IPAddress ipAddress = IPAddress.Parse(tcpIpAddress);
TcpListener tcpListener = new TcpListener(ipAddress, Convert.ToInt32(port));
tcpListener.Start();
Logger("'nWaiting for a client to connect...");
//blocks until a client connects
Socket socketForClient = tcpListener.AcceptSocket();
Logger("'nClient connected");
//Read data sent from client
NetworkStream networkStream = new NetworkStream(socketForClient);
int bytesReceived, totalReceived = 0;
string fileName = "testing.txt";
byte[] receivedData = new byte[10000];
do
{
bytesReceived = networkStream.Read
(receivedData, 0, receivedData.Length);
totalReceived += bytesReceived;
Logger("Progress of bytes recieved: " + totalReceived.ToString());
if (!File.Exists(fileName))
{
using (File.Create(fileName)) { };
}
using (var stream = new FileStream(fileName, FileMode.Append))
{
stream.Write(receivedData, 0, bytesReceived);
}
}
while (bytesReceived != 0);
Logger("Total bytes read: " + totalReceived.ToString());
socketForClient.Close();
Logger("Client disconnected...");
tcpListener.Stop();
}
catch (Exception ex)
{
// Error : "Only one usage of each socket address (protocol/network address/port) is normally permitted"
Logger("There is some error: " + ex.Message);
}
}
}).Start();
}
如何确保do-while
循环后的代码执行?
发件人代码:
private static void SendData(string tcpIpAddress, string port, string filename)
{
new Thread(
() =>
{
TcpClient tcpClient = new TcpClient(tcpIpAddress, Convert.ToInt32(port));
//const int bufsize = 8192;
const int bufsize = 10000;
var buffer = new byte[bufsize];
NetworkStream networkStream = tcpClient.GetStream();
using (var readFile = File.OpenRead(filename))
{
int actuallyRead;
while ((actuallyRead = readFile.Read(buffer, 0, bufsize)) > 0)
{
networkStream.Write(buffer, 0, actuallyRead);
}
}
}).Start();
}
如何确保do-while循环之后的代码执行?
在这里,这很容易,因为您可以关闭发送器上的连接,这将导致接收器读取零字节并终止循环。
事实上,你忘记清理发件人了。处置所有资源。这解决了问题。
您的代码将从代码审查SE中受益。我看到大约有十几个问题与此问题无关。这将是你提升自己的好方法。
例如,可以用Stream.Copy
替换复制循环。
我看到的通常方法是在发送的数据前加上即将发送的字节数。这样,接收器就知道数据包已被读取。即使网络中断,或者发件人发送其他内容时没有中断。
注意,这样做,你也可以在分配读取缓冲区之前读取前8个字节(如果Int32可以完成这项工作,则读取4个字节),这有助于优化缓冲区大小
另一种常见的方法是使用特定的终止符,但您必须保证发送的任何内容都不能包含该终止符