wpf+wcf 聊天程序(附源码)

提到聊天程序,一般都会想到socket,一边发,一边发,简单而又威武。
wpf支持绑定,支持类似动态刷新,而且wcf支持的服务用户更多,通信上,更是能做到伪peer to peer(就是p2p....笔者对这个一直很感兴趣) 的通信方式,说他是伪peer to peer方式,是因为可以把wcf服务当一个中转站,然后让每一个用户直接通信,而避免中转!只是个想法。。。。
好了,不扯皮了,三个工程,server host client

server端: 通信接口

 [ServiceContract(SessionMode = SessionMode.NotAllowed)]
    public interface IHost
    {
        [OperationContract]
        string Test();
        [OperationContract]
        bool ConnectCumm(string commId);
        [OperationContract]
        void ClientSend(string commId, string str);

        [OperationContract]
        List<string> GetHostMessage(string id);
    }

server实现

  public  class HostSvc:IHost
    {
        public string Test()
        {
            return "hello world!";
        }

         /// <summary>
         /// 添加一个客户端连接
         /// </summary>
         /// <param name="commId"></param>
         /// <returns></returns>
        public bool ConnectCumm(string commId)
        {
            var data = new FishComm(commId);
            return ListenComm.TryAdd(data);
        }

        public void ClientSend(string commId,string str)
        {
            ListenComm.ClientWriteMessage(commId,str);
        }


        public List<string> GetHostMessage(string id)
        {
            var data = ListenComm.GetMessage(id);
            return data;
        }
    }

static class ListenComm是自己写的缓存的静态类,里面写了简单的保存消息和服务器端发送消息

        /// <summary>
        /// 客户端获取服务器的信息列表
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static List<string> GetMessage(string id)
        {
            var data = _list.ContainsKey(id) ? _list[id].FishRecMessage : null;
            List<string> d = new List<string>();

            foreach (var temp in data)
            {
                d.Add(temp);
            }
            data.Clear();
            return d;
        }

        /// <summary>
        /// 服务器获取某一个客户端的信息列表
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static List<string> SendMessage(string id)
        {
            return _list.ContainsKey(id) ? _list[id].RecMessage : null;
        }
        /// <summary>
        /// 客户端写消息
        /// </summary>
        /// <param name="id"></param>
        public static void ClientWriteMessage(string id, string str)
        {
            var data = GetList.Find(p => p.Id == id);
            if (data == null) return;
            data.FishSendMessage.Add(data.FishId + ":" + str);
            FishCWriteMessage(null, new FishEnventArgs(data));
        }

        /// <summary>
        /// 服务器写消息
        /// </summary>
        /// <param name="id"></param>
        public static void HostWriteMessage(string id, string str)
        {
            var data = GetList.Find(p => p.Id == id);
            if (data == null) return;
            data.FishRecMessage.Add(str);
            FishHWriteMessage(null, new FishEnventArgs(data));
        }

总体思路是这样的,客户端和服务器各自 有一个List<string> 一个用于保存客户端的消息队列,一个用于保存服务器发送给客户端的消息,

客户端一直写消息,同时每隔一段间隔就会从服务器去消息,客户端有个timer定时取消息,当取了消息后,清空客户端的消息队列,就相当于双方通信了

  public class ClientVM : INotifyPropertyChanged
    {
        const string id = "爱喝可乐";
        DispatcherTimer dt;
        private ICommand _start;
        public ICommand Start
        {
            get
            {
                if (_start == null)
                {
                    _start = new DelegateCommand(p =>
                    {
                        new HostSvc.HostClient().ConnectCumm(id);
                        IsFree = false;
                        dt = new DispatcherTimer();
                        dt.Interval = new TimeSpan(500);
                        dt.Tick += new EventHandler(dt_Tick);
                        dt.Start();
                    }, o => IsFree);
                }
                return _start;
            }
        }

        void dt_Tick(object sender, EventArgs e)
        {
            var data = new HostSvc.HostClient().GetHostMessage(id);
            if (data != null)
            {
                foreach (var temp in data)
                {
                    RecText = "服务器:" + temp;
                }
            }
        }

        private ICommand _send;
        public ICommand Send
        {

            get
            {
                if (_send == null)
                {
                    _send = new DelegateCommand(p =>
                    {
                        new HostSvc.HostClient().ClientSend(id, SendText);
                        SendText = "";
                        //发送消息
                    }, o => true);
                }
                return _send;
            }
        }


        private bool _isFree = true;
        public bool IsFree
        {
            get { return _isFree; }
            set
            {
                if (_isFree != value)
                {
                    _isFree = value;
                    OnPropertyChange("IsFree");
                }
            }
        }

        private string _recText;
        public string RecText
        {
            get { return _recText; }
            set
            {
                _recText += value+"\n";
                OnPropertyChange("RecText");
            }
        }

        private string _sendText;
        public string SendText
        {
            get { return _sendText; }
            set
            {
                if (_sendText != value)
                {
                    _sendText = value;
                    OnPropertyChange("SendText");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChange(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    }

这是客户端的方法

下面是xmal

<Window x:Class="Client.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="408" Width="633">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="280" />
            <RowDefinition  />
        </Grid.RowDefinitions>
        <Button Command="{Binding Start}" Content="连接服务器" Width="80" Margin="0,0,422,0"></Button>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="120"></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <ListView ></ListView>

            <TextBox Grid.Column="1" Text="{Binding RecText}"/>
        </Grid>
        <TextBox Grid.Row="2" Text="{Binding SendText,Mode=TwoWay}" Height="30" Margin="0,6,98,16" />
        <Button Grid.Row="2" Command="{Binding Send}" Height="30" Content="发送" Width="80" Margin="486,6,12,15"/>
    </Grid>
</Window>

服务器端会有一个列表,每一个用户连接,就会记录连接用户的信息,然后就会有一个列表了,想给那个发就给那个发了

一个很简单的demo,只是抛砖引玉的意思,host要用管理员身份启动,然后客户端连接,然后进行通信,里面肯定有很多bug,只是一个简单的demo,

通信记录没有保存,只是一个临时的list进行暂存,还有其他比较好的方式,比如xml或者txt,不但可以保存,还可以多个用户同时进行,通信实现了,多个用过户通信也就没有问题,还可以加入一些声音,图片,或者视频,笔者只是抛砖引玉,如果以后有足够时间,笔者会加入进去的
没上传过源码,不知道这样行不行
https://files.cnblogs.com/fish124423/sumthesun.rar

原文地址:https://www.cnblogs.com/fish124423/p/2627807.html