以下为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
//{
// 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(() => { });
}
}