这几天折磨死我了,因为这玩意我也是自己在琢磨,然后资料也没有多少,简直就是自己慢慢摸索。

本期介绍如何利用TCP接收图片信息并显示。 首先我们先新建一个类,将我们想要的内容全部写到这个类上(类的代码会放在最后面)

cpListener用来创建监听,tcpClient用以发送。


public AndroidWifiService()
{

}
~AndroidWifiService()
{
    tcpClient?.Close();
    tcpClient = null;
    tcpListener = null;
    MessageReceived = null;
}
public AndroidWifiService(IPAddress address,int Port)
{
    StartListening(address, Port);
}

public AndroidWifiService(string address, int Port)
{
    StartListening(IPAddress.Parse(address), Port);
}

提供三种类型的构造函数和析构函数。


protected virtual void OnMessageReceived(byte[] buffer)
{
    // 触发事件
    MessageReceived?.Invoke(this, buffer);
}

设置一个事件,用以传递监听到的图片信息。


public async void StartListening(IPAddress IP,int Port)
{
    tcpListener = new TcpListener(IP, Port); 
    tcpListener.Start();

    while (true)
    {
        tcpClient = await tcpListener.AcceptTcpClientAsync();
        Task.Run(() => HandleClient(tcpClient));
    }
}

private void HandleClient(TcpClient client)
{
    try
    {
        NetworkStream stream = client.GetStream();
        byte[] buffer = new byte[1024]; // 使用固定大小的缓冲区
        using (MemoryStream ms = new MemoryStream())
        {
            int bytesRead;
            while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, bytesRead);
            }

            if (ms.Length > 0)
            {
                // 在主线程上更新 UI
                MainThread.BeginInvokeOnMainThread(() =>
                {
                    OnMessageReceived(ms.ToArray());
                });
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Exception in HandleClient: {ex.Message}");
    }
}

创建一个监听函数,注意的是,我们是接受完一次完整的流再传递信息,而不是边接收边传递


private void OnMessageReceived(object sender, byte[] message)
{
    MainThread.BeginInvokeOnMainThread(async () =>
    {
        try
        {
            using (MemoryStream ms = new MemoryStream(message))
            {
                SKBitmap bitmap = SKBitmap.Decode(ms);
                AndroidSaveClass save = new AndroidSaveClass();
                string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "MAUI_Picture_Save");
                if (!save.DoesFolderExist(folderPath))
                {
                    Directory.CreateDirectory(folderPath);
                }
                // 生成文件路径
                string uniqueFileName = $"sample_{DateTime.Now:yyyyMMddHHmmssfff}.png";
 
                string filePath = Path.Combine(folderPath, uniqueFileName);
                // 将 SKBitmap 编码并保存为 PNG 文件
                using (var image = SKImage.FromBitmap(bitmap))
                using (var data = image.Encode(SKEncodedImageFormat.Png, 100))
                using (var stream = File.OpenWrite(filePath))
                {
                    data.SaveTo(stream);
                }

                Picture.Source = filePath;

            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    });
}

再MainPage.xmal.cs中,我们新建一个这个类的变量,监听我们的窗口。并且设置回调函数用来处理事件。

事件中,我们将图片的字节数组转为图片,之后保存到程序的文件目录中,并且使用时间戳防止图片重复。

之后用Image控件来绑定图片源显示图片。

嘉立创PCB
全部评论 默认 最新
已折叠部分评论 展开
没有更多啦~