我正在尝试通过套接字传输文件,并在收到文件时将其写入文件(以便可以在其他应用程序中打开)。它主要工作,除了接近结尾(我猜)它阻塞,因为它试图读取整个8 KB的块,当没有那么多的东西接收。我不知道如何解决这个问题。我知道我应该接收的总字节数,如果有帮助的话。谢谢!
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) {
socket.Connect(e.IPAddress, e.Port);
using (var fs = new FileStream(e.Filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)) {
byte[] buffer = new byte[8192];
int read;
while ((read = socket.Receive(buffer)) > 0) {
fs.Write(buffer, 0, read);
}
}
}
答案 0 :(得分:-1)
如果没有可用于读取的数据,则接收方法将阻塞,直到数据可用,除非使用Socket.ReceiveTimeout设置超时值。如果超出超时值,则Receive调用将抛出SocketException。如果您处于非阻塞模式,并且协议堆栈缓冲区中没有可用数据,则Receive方法将立即完成并抛出SocketException。您可以使用Available属性来确定数据是否可供读取。当Available为非零时,重试接收操作。
Socket.Receive()
方法阻止,因为即使没有更多可用数据,连接仍在另一端打开。有几种方法可以解决这个问题,一种方法需要事先知道文件的大小,一旦读取了很多字节就停止另一种方法。另一种方法是使用非阻塞套接字(通过将Socket.Blocking属性设置为false)并从Socket.Available
属性获取数据。后者在编写代码时需要更多的技巧,因为读取操作不会再停止代码。
如果您事先知道数据的大小,可以将其与目前已阅读的数量进行比较,并在达到该数量后停止:
//If you know the size beforehand, set it as an int and compare
// it to what you have so far
int totalBytes = 9001;
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
socket.Connect(e.IPAddress, e.Port);
using (var fs = new FileStream(e.Filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read))
{
byte[] buffer = new byte[8192];
int read;
int bytesSoFar = 0; //Use this to keep track of how many bytes have been read
do
{
read = socket.Receive(buffer);
fs.Write(buffer, 0, read);
bytesSoFar += read;
} while (bytesSoFar < totalBytes);
}
}
请记住,第二个示例不是很强大,在尝试使用同一个套接字发送多个文件时无法正常工作。但是对于一个简单的1文件传输,这应该可以正常工作。