C# WPF 基于TCP协议,通过Socket类实现网络通信(服务端)(一个服务端对多个客户端进行通信)

直接Ctrl+c再Ctrl+v就能直接用了,纯小白教程。
运用了MVVM,Combobox内容动态绑定。

  • 前端.XMAL
    >
        
  • 后端.xmal.cs + INotifyPropertyChanged + ViewModel 【MVVM,动态绑定ComboBox内容】
public class NotifyPropertyChange : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void RaisePropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

    private ObservableCollection<string> _LClientItem = new ObservableCollection<string>();
    public ObservableCollection<string> LClientItem
        {
            get { return _LClientItem; }
            set { if (_LClientItem != value) { _LClientItem = value; RaisePropertyChanged(""); } }
        }
}

public class ViewModel
{
    #region 建立单例

    private static ViewModel uniqueInstance;

    private static readonly object locker = new object();

    public static ViewModel GetInstance()
        {
            if (uniqueInstance == null)
            {
                lock (locker)
                {
                    if (uniqueInstance == null)
                    {
                        uniqueInstance = new ViewModel();
                    }
                }
            }
            return uniqueInstance;
        }

    #endregion

    public NotifyPropertyChange m_NotifyPropertyChange = new NotifyPropertyChange();


}

/// 
    /// MainWindow.xaml 的交互逻辑
    /// 
public partial class MainWindow : Window
{

    public MainWindow()
        {
            InitializeComponent();

            this.DataContext = ViewModel.GetInstance().m_NotifyPropertyChange;
            ViewModel.GetInstance().m_NotifyPropertyChange.LClientItem.Add("AllConnection");
            C_RemoteEndPoint.SelectedIndex = 0;
            mySocketInit();
        }
    //初始化客户端类
    CsMySocketService mySocketService = new CsMySocketService();

    //初始化服务器IP和端口号+绑定消息接收事件
    private void mySocketInit()
        {
            mySocketService.strIpAddress = "127.0.0.1";
            mySocketService.nPort = 7788;

            mySocketService.ReceEvent += ReceClientDataClick;
        }

    private bool ReceTCP(string strIn)
        {
            var strCompare = strIn.Split('-');
            if (strCompare.Count() > 1)
            {
                if (strCompare[0] == "#TCP000")
                {
                    T_LocalEndPoint.Text = mySocketService.LocalEndPoint();
                    T_RemoteEndPoint.Text = strCompare[1];
                    ViewModel.GetInstance().m_NotifyPropertyChange.LClientItem.Add(strCompare[1]);
                    return false;
                }
                if (strCompare[0] == "#TCP404")
                {
                    ViewModel.GetInstance().m_NotifyPropertyChange.LClientItem.Remove(strCompare[1]);
                    T_RemoteEndPoint.Text = string.Format("{0}-已断开", strCompare[1]);
                    return false;
                }
                if (strCompare[1] == "")
                {
                    return false;
                }
            }
            return true;
        }

    private void ReceClientDataClick(string strIn)
        {
            System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate ()
            {
                if (!ReceTCP(strIn))
                    return;
                if (false)
                    TxRece.Text += strIn;
                else
                    TxRece.Text += strIn + "\r\n";
            });
        }

    private void BtTxSend_Click(object sender, RoutedEventArgs e) => mySocketService.SendData(C_RemoteEndPoint.Text, TxSend.Text);

    private void BtClearTxRece_Click(object sender, RoutedEventArgs e) => TxRece.Text = string.Empty;

    private void BtBreak_Click(object sender, RoutedEventArgs e) => mySocketService.SocketBreak(C_RemoteEndPoint.Text);

    private void BtConnect_Click(object sender, RoutedEventArgs e) => mySocketService.SocketFound();
}


  • 自定义服务端类
public class CsMySocketService
{
    /// 
        /// 作者:WangJunLiang || Wechat:Joronwongx
        /// 
    public CsMySocketService()//需要初始化
        {
            BackgroundWorker = new BackgroundWorker();
            BackgroundWorker.DoWork += FoundClientReceClick;
            BackgroundWorker.WorkerSupportsCancellation = true; //允许取消
        }

    private static Dictionary<string, Socket> LSocketClient = new Dictionary<string, Socket>();
    private static Dictionary<string, BackgroundWorker> LBackgroundWorkerClient = new Dictionary<string, BackgroundWorker>();

    private Socket tcpService = null;
    private BackgroundWorker BackgroundWorker = null;

    public delegate void ReceClientData(string strRece);
    public event ReceClientData ReceEvent;

    public string strIpAddress;
    public int nPort;

    //本地连接Point
    public string LocalEndPoint() => tcpService.LocalEndPoint.ToString();

    //创建连接
    public bool SocketFound()
        {
            try
            {
                if (tcpService != null)
                    return false;
                tcpService = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                EndPoint point = new IPEndPoint(IPAddress.Parse(strIpAddress), nPort);
                tcpService.Bind(point);
                tcpService.Listen(100);
                BackgroundWorker.RunWorkerAsync();//开始执行DoWork
                return true;
            }
            catch (System.Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                return false;
            }
        }

    //断开连接
    public bool SocketBreak(string strKey)
        {
            try
            {
                if (tcpService != null)
                {
                    if (tcpService != null)
                    {
                        if (strKey == "AllConnection")
                        {
                            BackgroundWorker.CancelAsync();
                            //通过IP和端口号来定位一个所要连接的服务器端
                            new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp).Connect(new IPEndPoint(IPAddress.Parse(strIpAddress), nPort));
                            //结束子客户端线程
                            foreach (var item in LSocketClient)
                            {
                                item.Value.Shutdown(SocketShutdown.Both);
                            }
                        }
                        else
                            LSocketClient[strKey].Shutdown(SocketShutdown.Both);
                    }
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                return false;
            }
        }

    //发送内容
    public void SendData(string strKey, string strIn)
        {
            try
            {
                if (tcpService != null)
                {
                    if (strKey == "AllConnection")
                        foreach (var item in LSocketClient)
                            item.Value.Send(Encoding.UTF8.GetBytes(strIn));//将字符串转化为字节数组,然后发送到服务器端
                    else
                        LSocketClient[strKey].Send(Encoding.UTF8.GetBytes(strIn));//将字符串转化为字节数组,然后发送到服务器端
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
        }

    //创建子客户端消息线程
    private void FoundClientReceClick(object sender, DoWorkEventArgs e)
        {
            Socket socketItem;
            while (!BackgroundWorker.CancellationPending)
            {
                socketItem = tcpService.Accept();
                if (BackgroundWorker.CancellationPending)
                    break;
                if (socketItem != null)
                {
                    BackgroundWorker ServiceBackgroundWorker = new BackgroundWorker();
                    ServiceBackgroundWorker.DoWork += ReceClientDataClick;
                    ServiceBackgroundWorker.WorkerSupportsCancellation = true; //允许取消

                    //子客户端 ip+point
                    var strRp = socketItem.RemoteEndPoint.ToString();
                    LSocketClient.Add(strRp, socketItem);
                    LBackgroundWorkerClient.Add(strRp, ServiceBackgroundWorker);
                    ReceEvent(string.Format("#TCP000-{0}", strRp));
                    ServiceBackgroundWorker.RunWorkerAsync(socketItem);//开始执行DoWork
                }
            }
            tcpService.Close();
            tcpService = null;
        }

    //内容监听 socketItem代表子客户端的id
    private void ReceClientDataClick(object sender, DoWorkEventArgs e)
        {
            Socket socketItem = (Socket)e.Argument;
            var strRp = socketItem.RemoteEndPoint.ToString();
            while (!LBackgroundWorkerClient[strRp].CancellationPending)
            {
                try
                {
                    if (socketItem.Poll(10, SelectMode.SelectRead))
                    {
                        LBackgroundWorkerClient[strRp].CancelAsync();//停止执行DoWork
                        break;
                    }
                    byte[] data = new byte[1024];  //传递一个byte数组,用于接收数据。length表示接收了多少字节的数据
                    int length = socketItem.Receive(data);
                    string strOut = Encoding.UTF8.GetString(data, 0, length);//只将接收到的数据进行转化 =========阻塞======
                    ReceEvent(string.Format("[{0}]-{1}", strRp, strOut));
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                    ReceEvent(string.Format("[{0}]-{1}", strRp, ex.Message));
                }
            }
            ReceEvent(string.Format("#TCP404-{0}", strRp));
            LSocketClient[strRp].Shutdown(SocketShutdown.Both);
            LSocketClient[strRp].Close();
            LBackgroundWorkerClient.Remove(strRp);
            LSocketClient.Remove(strRp);
        }
}

你可能感兴趣的:(C#,c#,socket,tcpip)