我已经实现了一个异步函数来读取大型套接字数据,大多数文件都会被传输。代码基于this question:
public class StateObject
{
public Socket workSocket = null;
public const int BUFFER_SIZE = 1024;
public byte[] buffer = new byte[BUFFER_SIZE];
public StringBuilder sb = new StringBuilder();
}
public static void Read_Callback(IAsyncResult ar)
{
StateObject so = (StateObject) ar.AsyncState;
Socket s = so.workSocket;
int read = s.EndReceive(ar);
if (read > 0)
{
so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));
if (read == StateObject.BUFFER_SIZE)
{
s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0,
new AyncCallback(Async_Send_Receive.Read_Callback), so);
return;
}
}
if (so.sb.Length > 0)
{
//All of the data has been read, so displays it to the console
string strContent;
strContent = so.sb.ToString();
Console.WriteLine(String.Format("Read {0} byte from socket" +
"data = {1} ", strContent.Length, strContent));
}
s.Close();
}
在stringbuilder中捕获了所有数据之后,我解密它并使用另一种方法将base64字符串转换为文件。将有多个套接字接收\发送文件,因此每个workersocket都有一个ID。
现在是这样的;我想在接收文件上有一些状态。例如,进度条显示接收的数量和要接收的总金额。 Read_Callback方法使用递归调用来从套接字获取所有数据,这使我无法获得要接收的总量。有谁知道如何获得套接字必须接收的总金额?或者是我唯一的选择,在传输数据之前发送固定到侦听器的大小?
如前所述,我的stateobject类包含一个ID,用于标识数据所针对的套接字。在第一次连接时,程序将连接和接收的信息存储在arraylist中。
为了获取已读取的字节数,我必须将状态报告给存储在arraylist中的一个已启动的工作类。如果我想在递归调用期间执行此操作,在接收数据时如何执行此操作而不会失去性能?
最后,应该使用哪个缓冲区大小?这应该是tcp的MTU,在大多数情况下是1500字节吗?
答案 0 :(得分:1)
我建议在发送实际文件之前,将总文件大小作为通信的第一步发送。例如,你的StateObject类可以有一个额外的属性,它保存你传输的东西的总大小,然后在另一个线程(UI线程)中,你可以创建一个进度条,并根据传输的总数与总的大小来报告。文件百分比或任何你喜欢的。只需跟踪已发生的数据传输量,并在适当时更新对象。
答案 1 :(得分:0)
除了CG的答案之外,我还会跳过stringbuilder并使用类似的东西:
FileStream fs = File.OpenRead(filePath);
Byte[] bytes = new Byte[fs.Length];
fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
fs.Close();