【问题标题】:c# Creating header of file name and size while sending file in socket connectionc#在套接字连接中发送文件时创建文件名和大小的标题
【发布时间】:2019-02-19 18:02:52
【问题描述】:

我已成功使用以下方法在我的套接字连接中将文件大小信息从服务器发送到客户端:

对于服务器:

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

现在如果我也想向客户端发送文件名,最好的方法是什么?

是我将它添加到标题中吗?我们如何添加它?

或者我单独发送并在客户端为它创建另一个回调?

【问题讨论】:

  • 你可以对文件名使用类似的方法,它只是一个可变长度的字符串,就像文件是一个可变长度的文件一样 - 发送字符串的长度,然后是字符串本身。跨度>
  • 伊恩,你的意思是我将它添加到文件大小的标题中?我们该怎么做?
  • 将文件名字符串编码为字节数组,然后发送数组长度后跟数组。就像您处理文件数据一样。

标签: c# .net sockets tcp tcp-ip


【解决方案1】:

我认为假设您的客户端第一次完成读取时它只会读取服务器作为标头发送的字节是不明智的。你最好在这里定义一个规范;决定一些任意的东西,比如发送的数据应该是

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

然后您的客户可以接收并重新组装文件

或者实现一个现有的协议,比如http

【讨论】:

  • 你的意思是用分号分隔数据?当客户端收到刚刚拆分的字节时读取分号?它很难与 http 进行比较,因为 http 是字符串,但我的数据是字节。
  • 如果您使用分隔符,请不要使用在文件名中有效的分隔符,例如分号!结肠很好。
  • 您确定字节形式的数据不会包含冒号吗?
  • 字符串,字节,都是字节!字符串由字节组成。你决定你希望这个协议是什么样子。使用 xml,使用 http,使用固定宽度.. 这是任意的 => 你决定
  • 我使用的是字节,所以我的信息是十六进制的......所以数据中没有冒号的 0x3A 对吗?
猜你喜欢
  • 2012-01-30
  • 1970-01-01
  • 2017-03-14
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-15
相关资源
最近更新 更多