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,不但可以保存,還可以多個用戶同時進行,通信實現了,多個用過戶通信也就沒有問題,還可以加入一些聲音,圖片,或者視頻,筆者只是拋磚引玉,如果以后有足夠時間,筆者會加入進去的
沒上傳過源碼,不知道這樣行不行
http://files.cnblogs.com/fish124423/sumthesun.rar


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM