这几天折磨死我了,因为这玩意我也是自己在琢磨,然后资料也没有多少,简直就是自己慢慢摸索。
本期介绍如何利用TCP接收图片信息并显示。 欢迎大家加入交流群分享经验: ** 656210280 **
首先我们先新建一个类,将我们想要的内容全部写到这个类上(类的代码会放在最后面)
tcpListener用来创建监听,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控件来绑定图片源显示图片。
这样子图片就传递成功啦。
namespace MAUIapp.Platforms.Android.Servers{ public class AndroidWifiService : IWifiService { TcpListener? tcpListener; TcpClient? tcpClient;
public event EventHandler<byte[]>? MessageReceived;
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 bool TCP_Send(string message,string IP ,int Port) { try { if (tcpClient == null || !tcpClient.Connected) { // 创建并连接到服务器 tcpClient = new TcpClient(IP,Port); // 请替换成你的服务器的IP地址 }
// 发送消息 using (NetworkStream stream = tcpClient.GetStream()) { byte[] buffer = Encoding.UTF8.GetBytes(message); stream.Write(buffer, 0, buffer.Length); }
return true; } catch (Exception ex) { Console.WriteLine($"TCP_Send Exception: {ex.Message}"); return false; } } 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}"); } }
}
}