zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    腾讯与唯品会笔试面试经历
    JavaCodeTra 猴子选猴王 约瑟夫循环
    HBase开发错误记录(一):java.net.UnknownHostException: unknown host: master
    fedora
    Qt5.1 静态编译
    Linux/Ubuntu下 静态编译Qt程序
    地铁车型
    交流屏和直流屏的区别
    不间断电源(UPS)
    一级负荷供电
  • 原文地址:https://www.cnblogs.com/fish124423/p/2627807.html
Copyright © 2011-2022 走看看