c # Создание заголовка имени и размера файла при отправке файла в сокет соединение - PullRequest
0 голосов
/ 15 сентября 2018

Я успешно использую следующее для отправки информации о размере файла с сервера на клиент в моем сокет-соединении:

Для сервера:

    public void SendFiles(Socket client, string filePath)
    {
        byte[] imgBuff = File.ReadAllBytes(filePath);
        var length = imgBuff.Length;

        Send(client, BitConverter.GetBytes(length)); //Send file size in header info
        Send(client, imgBuff);  //Send the file
    }

Для Клиента я два раза получаю обратный вызов:

    private void Receive(Socket client)
    {
        try
        {
            StateObject state = new StateObject();
            state.workSocket = client;

            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReceiveHeaderCallback), state);
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
        }
    }

    public static void ReceiveHeaderCallback(IAsyncResult ar)
    {
        try
        {
            Debug.WriteLine("## Begin ReceiveHeaderCallback");
            StateObject state = (StateObject)ar.AsyncState;
            Socket handler = state.workSocket;

            int bytesRead = handler.EndReceive(ar);

            state.fileSize = BitConverter.ToInt32(state.buffer, 0);
            _Buff = new byte[state.fileSize];
            _totBytesRead = 0;
            Debug.WriteLine("## File size = " + state.fileSize);

            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
               new AsyncCallback(ReceiveCallback), state);
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
        }
    }

    private static void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.workSocket;

            int bytesRead = client.EndReceive(ar);

            if (bytesRead > 0)
            {
                // There  might be more data, so store the data received so far.
                Buffer.BlockCopy(state.buffer, 0, _Buff, _totBytesRead, bytesRead);

                _totBytesRead += bytesRead;

                if (_totBytesRead < state.fileSize)
                {
                    // Not all data received. Get more.
                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);
                }
                else
                {
                    File.WriteAllBytes(@"c:\abc.png", _Buff);
                    Debug.WriteLine("## File receiving complete. File created at ");
                }
            }
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
        }
    }

Теперь, если я тоже хочу отправить имя файла клиенту, каков наилучший способ сделать это?

Это я добавляю его в шапку? Как мы добавим это?

Или я отправляю отдельно, а на стороне клиента создаю для него еще один обратный вызов?

1 Ответ

0 голосов
/ 15 сентября 2018

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

<length>:<file name>:<file bytes>

Тогда ваш клиент может получить и собрать файл

Или реализовать существующий протокол, например http

...