【C#】WCF和TCP消息通信练习,实现群聊功能

简介: 实现群聊功能

WCF和TCP消息通信练习

客户端

MainWindow.xaml

主页面
在这里插入图片描述

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Lab_5
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void StartWindow(string userName, int left, int top)
        {
            ChatCline w = new ChatCline();
            w.Left = left;
            w.Top = top;
            w.UserName = userName;
            w.Owner = this;
            w.Closed += (sender, e) => this.Activate();//关闭子窗体时激活父窗体
            w.Show();
        }

        private void bt1_Click(object sender, RoutedEventArgs e)
        {
            StartWindow("用户1", 0, 0);
            StartWindow("用户2", 400, 300);
        }

        private void bt2_Click(object sender, RoutedEventArgs e)
        {
            ChatCline w = new ChatCline();
            w.Owner = this;
            w.Closed += (sendObj, args) => this.Activate();
            w.Show();
        }
    }
}

ChatCline.xaml

聊天界面
在这里插入图片描述

ChatCline.xaml.cs

using Lab_5.ServiceReference1;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Lab_5
{
    /// <summary>
    /// ChatCline.xaml 的交互逻辑
    /// </summary>
    public partial class ChatCline : Window,IService1Callback
    {
        public ChatCline()
        {
            InitializeComponent();
            this.Closing += ChatCline_Closing;
            box.Visibility = System.Windows.Visibility.Hidden;
        }

        private Service1Client client;

        public string UserName
        {
            get { return textbox.Text; }
            set { textbox.Text = value; }
        }

        private void ChatCline_Closing(object sender, CancelEventArgs e)
        {
            if (client != null)
            {
                client.Logout(UserName); 
                client.Close();
            }
        }

        private void AddMessage(string str)
        {
            TextBlock t = new TextBlock();
            t.Text = str;
            listmessage.Items.Add(t);
        }

        public void InitUsersInfo(string UsersInfo)
        {
            if (UsersInfo.Length == 0) return;
            string[] users = UsersInfo.Split('、');
            for (int i = 0; i < users.Length; i++)
            {
                listbox.Items.Add(users[i]);
            }
        }

        public void ShowLogin(string loginUserName)
        {
            if (loginUserName == UserName)
            {
                box.Visibility = System.Windows.Visibility.Visible;
            }
            listbox.Items.Add(loginUserName);
        }

        public void ShowLogout(string userName)
        {
            listbox.Items.Remove(userName);
        }

        public void ShowTalk(string userName, string message)
        {
            AddMessage(userName+"说: "+message);
        }

        private void login_Click(object sender, RoutedEventArgs e)
        {
            UserName = textbox.Text;
            InstanceContext context = new InstanceContext(this);
            client = new Service1Client(context);
            try
            {
                client.Login(textbox.Text);
                login.IsEnabled = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show("与服务端连接失败:" + ex.Message);
                return;
            }
        }

        private void launch_Click(object sender, RoutedEventArgs e)
        {
            client.Talk(UserName, messagebox.Text);
            messagebox.Text = "";
        }


        private void messagebox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                client.Talk(UserName, messagebox.Text);
                messagebox.Text = "";
            }
        }
    }
}

服务端

Users.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WcfServiceLibrary1
{
    class Users
    {
        public string UserName { get; set; }
        public readonly IService1Callback callback;

        public Users(string userName, IService1Callback callback)
        {
            this.UserName = userName;
            this.callback = callback;
        }
    }
}

CC.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WcfServiceLibrary1
{
    class CC
    {
        public static List<Users> Users { get; set; }

        static CC()
        {
            Users = new List<Users>();
        }

        public static Users GetUser(string userName)
        {
            Users user = null;
            foreach (var v in Users)
            {
                if (v.UserName == userName)
                {
                    user = v;
                    break;
                }
            }
            return user;
        }
    }
}

IService1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WcfServiceLibrary1
{
    [ServiceContract(Namespace = "IService",
        CallbackContract = typeof(IService1Callback))]
    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。
    public interface IService1
    {

        // TODO: 在此添加您的服务操作
        [OperationContract(IsOneWay = true)]
        void Login(string userName);

        [OperationContract(IsOneWay = true)]
        void Logout(string userName);

        [OperationContract(IsOneWay = true)]
        void Talk(string userName, string message);
    }


    public interface IService1Callback
    {
        [OperationContract(IsOneWay = true)]
        void ShowLogin(string loginUserName);

        [OperationContract(IsOneWay = true)]
        void ShowLogout(string userName);

        [OperationContract(IsOneWay = true)]
        void ShowTalk(string userName, string message);

        [OperationContract(IsOneWay = true)]
        void InitUsersInfo(string UsersInfo);
    }

}

Service1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WcfServiceLibrary1
{
    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“Service1”。
    public class Service1 : IService1
    {
        public void Login(string userName)
        {
            OperationContext context = OperationContext.Current;
            IService1Callback callback = context.GetCallbackChannel<IService1Callback>();
            Users newUser = new Users(userName, callback);
            string str = "";
            for (int i = 0; i < CC.Users.Count; i++)
            {
                str += CC.Users[i].UserName + "、";
            }
            newUser.callback.InitUsersInfo(str.TrimEnd('、'));
            CC.Users.Add(newUser);
            foreach (var user in CC.Users)
            {
                user.callback.ShowLogin(userName);
            }
        }

        public void Logout(string userName)
        {
            Users logoutUser = CC.GetUser(userName);
            CC.Users.Remove(logoutUser);
            logoutUser = null;
            foreach (var user in CC.Users)
            {
                user.callback.ShowLogout(userName);
            }
        }

        public void Talk(string userName, string message)
        {
            Users user = CC.GetUser(userName);
            foreach (var v in CC.Users)
            {
                v.callback.ShowTalk(userName, message);
            }
        }
    }
}

实验结果

在这里插入图片描述

通过本次练习简单掌握了WCF和TCP消息通信,实现聊天

目录
相关文章
|
5月前
|
C#
【C#】 如何实现文本框历史记录提示功能
【C#】 如何实现文本框历史记录提示功能
88 0
|
5月前
|
数据处理 C# C++
如何使用C#和C++结构体实现Socket通信
如何使用C#和C++结构体实现Socket通信
200 0
|
5月前
|
监控 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
80 0
|
5月前
|
数据采集 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用ForceIP强制修改网口IP功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用ForceIP强制修改网口IP功能(C#)
53 0
|
5月前
|
安全 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用短曝光功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用短曝光功能(C#)
66 0
|
5月前
|
编解码 监控 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Binning像素合并功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Binning像素合并功能(C#)
50 0
|
5月前
|
存储 编解码 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用UserSet功能保存和载入相机的各类参数(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用UserSet功能保存和载入相机的各类参数(C#)
80 0
|
5月前
|
编译器 C# 开发工具
C# 12 中新增的几大功能你都知道吗?
C# 12 中新增的几大功能你都知道吗?
|
2月前
|
编译器 API C#
C# 12 新增功能实操!
C# 12 新增功能实操!
|
2月前
|
物联网 C# Windows
看看如何使用 C# 代码让 MQTT 进行完美通信
看看如何使用 C# 代码让 MQTT 进行完美通信
335 0