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

本文介绍了在WPF项目中,如何使用标志位q来处理TCP服务器接收到的数据,以解决粘包问题,包括Socket对象的使用、事件监听和数据解析过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潘诺西亚的火山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值