.net中用标志位解决socket粘包问题

以下为wpf中, 用标志位"q" 解决粘包问题

csharp 复制代码
using MyFrameWorkWpf.Entities;
using System.Collections.ObjectModel;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace MyFrameWorkWpf.ViewModels
{
    public partial class TcpServerViewModel : ObservableObject
    {
        public TcpServerViewModel()
        {
            myIp = "192.168.2.100";
            myPort = "8888";


        }

        //声明一个Socket对象
        private Socket socketServer = new Socket(
            AddressFamily.InterNetwork,
            SocketType.Stream,
            ProtocolType.Tcp
        );

        private CancellationTokenSource cts = new();
        private ManualResetEvent resetEvent = new ManualResetEvent(true);
        private static readonly object lockObj = new object(); // 创建一个对象作为锁
        private readonly MyRArr myRArr;

        //创建字典集合,键是ClientIp,值是SocketClient
        private Dictionary<string, Socket> currentClientlist = new Dictionary<string, Socket>();

        private ObservableCollection<string> serverList = new();

        public ObservableCollection<string> ServerList
        {
            get => serverList;
            set => SetProperty(ref serverList, value);
        }

        private string myIp = "";

        public string MyIp
        {
            get => myIp;
            set => SetProperty(ref myIp, value);
        }

        private string myPort = "";

        public string MyPort
        {
            get => myPort;
            set => SetProperty(ref myPort, value);
        }

        private ObservableCollection<TcpMessage> reciveData = new();

        public ObservableCollection<TcpMessage> ReciveData
        {
            get => reciveData;
            set => SetProperty(ref reciveData, value);
        }

        private string sendTxt = "";

        public string SendTxt
        {
            get => myPort;
            set => SetProperty(ref myPort, value);
        }

        private bool isEnabled = true;

        public bool IsEnable
        {
            get => isEnabled;
            set => SetProperty(ref isEnabled, value);
        }

        public RelayCommand<RadioButton> SelectView { get; private set; }

        //public RelayCommand<Button> ConnCommand => new RelayCommand<Button>((args) =>
        //{
        //    if (!(args is Button button)) return;
        //});

        public RelayCommand<Button> ConnCommand =>
            new RelayCommand<Button>((args) =>
            {
                if (!(args is Button button)) return;

                if (MyIp != null && MyPort != null)
                {
                    IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(MyIp), int.Parse(this.MyPort));

                    try
                    {
                        socketServer.Bind(ipe);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                        return;
                    }
                    MessageBox.Show("服务器开启成功");
                    button.IsEnabled = false;
                    //IsEnabled = false;
                    //只监听一个
                    socketServer.Listen(1);

                    //创建一个监听的线程

                    Task.Run(
                        new Action(async () =>
                        {
                            while (!cts.IsCancellationRequested)
                            {
                                // 第四步:调用accept()函数来接受客户端的连接,这是就可以和客户端通信了。
                                Socket? socketClient = socketServer.Accept();

                                string? client = socketClient?.RemoteEndPoint?.ToString();
                                if (socketClient != null && client != null)
                                {
                                    currentClientlist.Add(client, socketClient);
                                    Application.Current.Dispatcher.Invoke(() =>
                                    {
                                        ServerList.Add(client);
                                    });

                                    await Task.Delay(500);

                                    // 创建一个缓冲区

                                    while (!cts.IsCancellationRequested)
                                    {
                                        byte[] buffer = new byte[1024 * 1024 * 10];
                                        int length = -1;

                                        // 第五步:处理客户端的连接请求。
                                        try
                                        {

                                            //length = socketClient.ReceiveFrom(buffer, 0, 8192, SocketFlags.None, ref remoteEP);
                                            if (ServerList.Count > 0)
                                            {
                                                length = currentClientlist[ServerList[0]].Receive(
                                                    buffer
                                                );
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            ServerList.Remove(client);
                                            currentClientlist.Remove(client);
                                            MessageBox.Show(ex.Message);
                                            break;
                                        }

                                        if (length > 0)
                                        {
                                            byte[] temp = new byte[length];
                                            //buffer复制到temp
                                            Array.Copy(buffer, 0, temp, 0, length);


                                            byte[] separator = Encoding.UTF8.GetBytes("q");
                                            //q所在的索引位置
                                            int idx = Array.IndexOf(buffer, separator[0], 0, length);
                                            if (idx >= 0)
                                            {
                                                var data = Encoding.ASCII.GetString(temp);
                                                var res = data.Substring(0, idx); //截取索引之前的数据

                                                TcpMessage tcpMessage = new();
                                                lock (lockObj)
                                                {
                                                    tcpMessage.DateTime = DateTime.Now;
                                                    tcpMessage.Message = res;
                                                    tcpMessage.Client = ServerList[0];
                                                }

                                                Application.Current.Dispatcher.Invoke(() =>
                                                {
                                                    ReciveData.Add(tcpMessage);
                                                });
                                            }

                                            //string msg = string.Empty;
                                            //msg = Encoding.ASCII.GetString(buffer, 0, length);

                                            //TcpMessage tcpMessage = new();
                                            //lock (lockObj)
                                            //{
                                            //    tcpMessage.DateTime = DateTime.Now;
                                            //    tcpMessage.Message = msg;
                                            //    tcpMessage.Client = ServerList[0];
                                            //}

                                            //Application.Current.Dispatcher.Invoke(() =>
                                            //{
                                            //    ReciveData.Add(tcpMessage);
                                            //});
                                        }
                                    }
                                }
                            }
                        }),
                        cts.Token
                    );
                }
                else
                {
                    MessageBox.Show("Ip,端口号不能为空!");
                }
            });

        public RelayCommand DisConnCommand => new RelayCommand(() => { });

        public RelayCommand SendMsgCommand =>
            new RelayCommand(() =>
            {
                byte[] send = Encoding.ASCII.GetBytes(SendTxt);

                //创建最终发送的数组
                byte[] sendMsg = new byte[send.Length];

                //整体拷贝数组
                Array.Copy(send, 0, sendMsg, 0, send.Length);

                if (ServerList.Count > 0)
                {
                    string client = ServerList[0];
                    currentClientlist[client]?.Send(sendMsg);
                }
                SendTxt = string.Empty;
            });

        public RelayCommand EditCommand => new RelayCommand(() => { });
    }
}
相关推荐
洁辉1 小时前
C# & .NET 面试深度复习指南
面试·c#·.net
ChaITSimpleLove1 小时前
.NET9 实现对象深拷贝和浅拷贝的性能测试
.net·性能测试·浅拷贝·深拷贝·deep copy·shallow copy
cui_win1 小时前
【网络】Linux 内核优化实战 - net.netfilter.nf_conntrack_buckets
linux·网络·.net
cui_win1 小时前
【网络】Linux 内核优化实战 - net.netfilter.nf_conntrack_tcp_timeout_established
linux·网络·.net
喵叔哟1 小时前
27.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--币种服务(一)
微服务·架构·.net
木卯彳亍9 小时前
番外-linux系统运行.net framework 4.0的项目
linux·docker·.net
时光追逐者10 小时前
一款开源免费、通用的 WPF 主题控件包
开源·c#·.net·wpf
每日出拳老爷子18 小时前
[WinForms] 如何为 .NET Framework 4.8 窗体程序添加自定义图标
visualstudio·c#·.net
Yan901818 小时前
.net解析雷达拼图3.0组合反射率产品,并按经纬度裁剪绘制组合反射率图
.net
步、步、为营19 小时前
.net服务器Kestrel配置Nginx作为反向代理
服务器·nginx·.net