C#异步套接字Begin / EndReceive问题

时间:2010-08-16 09:27:49

标签: c# sockets asynchronous

我已经实现了一个异步函数来读取大型套接字数据,大多数文件都会被传输。代码基于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字节吗?

2 个答案:

答案 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();