C # асинхронный сокет Begin / EndReceive вопросы - PullRequest
0 голосов
/ 16 августа 2010

Я реализовал асинхронную функцию для чтения больших данных сокетов, в основном файлы будут передаваться. Код основан на этом вопросе :

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();
}

После того как все данные были собраны в строителе строк, я расшифровываю их и преобразую строку base64 в файл другим способом. Будет несколько сокетов, принимающих \ отправляющих файлы, поэтому каждый рабочий сокет имеет идентификатор.

Теперь вот случай; Я хочу получить статус в файле получения. Например, индикатор выполнения, показывающий, сколько получено, и общую сумму, которую нужно получить. Метод Read_Callback использует рекурсивный вызов, чтобы получить все данные из сокета, что не позволяет мне получить общую сумму, которую необходимо получить. Кто-нибудь знает, как получить общую сумму, которую должен получить сокет? Или мой единственный способ отправить фиксированный размер слушателю перед передачей данных?

Как упоминалось ранее, мой класс stateobject содержит идентификатор для идентификации сокета, для которого предназначены данные. При первом соединении программа сохраняет соединение и полученную информацию в массиве.

Чтобы получить количество прочитанных байтов, я должен сообщить о состоянии одному из инициированных рабочих классов, хранящихся в массиве. Если я хочу сделать это во время рекурсивного вызова, как я буду выполнять это без потери производительности при получении данных?

Как последний, какой размер буфера следует использовать? должен ли это быть MTU tcp, который в большинстве случаев составляет 1500 байт?

Ответы [ 2 ]

1 голос
/ 16 августа 2010

Я бы посоветовал отправить общий размер файла в качестве первого шага в вашем общении, прежде чем отправлять по фактическому файлу. Например, ваш класс StateObject может иметь дополнительное свойство, которое содержит общий размер передаваемой вами вещи, тогда в другом потоке (потоке пользовательского интерфейса) вы можете создать индикатор выполнения и отчет на основе общего количества переданных и общего размера файл в процентах или как угодно. Просто отследите, сколько данных было передано по мере их появления, и соответствующим образом обновите ваш объект.

0 голосов
/ 16 августа 2010

В дополнение к ответу CG, я бы также пропустил построитель строк и использовал что-то вроде:

        FileStream fs = File.OpenRead(filePath);
        Byte[] bytes = new Byte[fs.Length];
        fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
        fs.Close();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...