асинхронный сетевой поток в файловый поток (наоборот) - PullRequest
1 голос
/ 12 января 2011

У меня есть приложение клиент / сервер.Они оба используют асинхронные вызовы при получении данных.его сборка с TCP и предназначена, главным образом, для отправки файлов.

Команда отправляется по сокету, который затем «конвертируется» в действие и выполняется с простым переключением.Если клиент отправляет команду «SENDFILE», я хочу, чтобы сервер мог вводить регистр, который вызывает функцию, которая затем обрабатывает любые дополнительные данные по этому сокету и объединяет их в файл.

Это обратный вызов OnDataReceive.регистр функции и коммутатора на стороне сервера:

public void OnDataReceived(IAsyncResult asyn)
        {
            SocketData socketData = (SocketData)asyn.AsyncState;
            try
            {

                // Complete the BeginReceive() asynchronous call by EndReceive() method
                // which will return the number of characters written to the stream 
                // by the client
                socketData.m_currentSocket.EndReceive(asyn);

                //Get packet dtata
                Packet returnPacket = Helper.ByteArrayToPacket(socketData.dataBuffer);

                switch (returnPacket.command)
                {
                    case Command.SENDREQUEST: //Get ready for an incoming file      

Здесь класс, который читает из сетевого потока асинхронно и записывает в файловый поток синхронно: Это верно?

    public static void NetToFile(NetworkStream net, FileStream file)
        {
            var copier = new AsyncStreamCopier(net, file);
            copier.Start();
        }

public class AsyncStreamCopier
    {
        public event EventHandler Completed;

        private readonly Stream input;
        private readonly Stream output;

        private byte[] buffer = new byte[Settings.BufferSize];

        public AsyncStreamCopier(Stream input, Stream output)
        {
            this.input = input;
            this.output = output;
        }

        public void Start()
        {
            GetNextChunk();
        }

        private void GetNextChunk()
        {
            input.BeginRead(buffer, 0, buffer.Length, InputReadComplete, null);
        }

        private void InputReadComplete(IAsyncResult ar)
        {
            // input read asynchronously completed
            int bytesRead = input.EndRead(ar);

            if (bytesRead == 0)
            {
                RaiseCompleted();
                return;
            }

            // write synchronously
            output.Write(buffer, 0, bytesRead);

            // get next
            GetNextChunk();
        }

        private void RaiseCompleted()
        {
            if (Completed != null)
            {
                Completed(this, EventArgs.Empty);
            }
        }
    }

Проблемау меня есть обратное, чтение из файлового потока в сетевой поток, я должен читать из файлового потока асинхронно и записывать синхронно в сетевой поток?

также потому, что в приведенном выше примере первый раз Start ()Вызывается, и функция завершается, она возвращается к случаю коммутатора сервера, и любые дальнейшие (файловые) данные затем нажимают Packet returnPacket = Helper.ByteArrayToPacket(socketData.dataBuffer);

и выдают ошибку :(

* РЕДАКТИРОВАТЬ 1 *

  • Я не могу использовать какие-либо внешние библиотеки или большие объемы кода, его необходимо собрать изНачинаем.

  • Это не типичное клиент-серверное приложение, оно более p2p, но не совсем, у каждого приложения есть собственный сервер и клиент, работающий в разных потоках, это позволяет использовать несколько приложений.чтобы все соединялись друг с другом, создавая ... сеть.

  • Клиент сообщает серверу, что отправляет ему файл, он не запрашивает файл с сервера

Ответы [ 3 ]

0 голосов
/ 12 января 2011

Ознакомьтесь с этой статьей об асинхронных операциях с потоками http://msdn.microsoft.com/en-us/magazine/cc337900.aspx (имейте компактный код, который асинхронно копирует потоки).

В вашем примере кода не используется заполненное уведомление о том, что вы ... Убедитесь, что вашвнешний код ожидает завершения копирования потока.

0 голосов
/ 12 января 2011

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

Проблема, с которой я сейчас сталкиваюсь, заключается вфайловый поток -> сетевой поток.«я должен читать из файлового потока асинхронно и синхронно записывать в сетевой поток?»

0 голосов
/ 12 января 2011

Ну, я не думаю, что есть прямой ответ на ваш вопрос; Тем не менее, вот несколько замечаний:

Если клиент отправляет команду "SENDFILE", я хочу, чтобы сервер мог ...

Это подход; Тем не менее, вы можете посмотреть на инвертирование управления немного больше. Иметь информацию о файле извлечения, которая возвращает информацию о размере / версии. Затем получите файл для чтения, который принимает смещение и длину. Теперь клиент может «опросить» свой путь через файл, а не пытаться получить данные так быстро, как сервер может их отправить.

Здесь класс, который читает из сетевого потока асинхронно и записывает в файловый поток синхронно: Это верно?

Да, с первого взгляда.

Проблема, с которой я сталкиваюсь, заключается в том, чтобы делать обратное - читать из файлового потока в сетевой поток. Должен ли я читать из файлового потока асинхронно и записывать синхронно в сетевой поток?

Опять же, я бы использовал цикл опроса клиента для одновременного извлечения фрагментов файла. Затем его также можно перезапустить, если розетка будет отсоединена.

также потому, что в вышеприведенном примере вызывается первый раз Start () и функция заканчивается ...

Да, это вообще проблема с сокетами. Вам нужно будет отслеживать информацию о состоянии каждого сокета, чтобы вы знали, что делать с полученными байтами. Пишу ли я в файл, жду ли я команды и т. Д. Честно говоря, если бы я писал это (чего бы я ни делал с сокетами), я бы упаковал все в префикс длины google protobuffer , содержащий подробности о каждом запросе. Это позволяет разгрузить управление состоянием на клиенте, а не отслеживать его на сервере.

Может ли кто-нибудь указать мне правильное направление? из того, что я вижу, не так много в сети.

Я думаю, что общая причина, по которой вы мало что находите в этом поиске в сети, заключается в том, что большинство (90% или около того) даже не пытаются это сделать. Делать это с помощью сокетов сложно, утомительно и чрезвычайно подвержено ошибкам. Я бы даже не стал использовать сырые сокеты для общения. Выберите любой существующий клиент / серверный транспорт и используйте его. Моя рекомендация, вероятно, будет опираться на WCF, если вам потребуются примеры.

Ура и удачи!

...