利用C#編寫的網路聊天程式

來源:互聯網
上載者:User

1、程式分為伺服器端和用戶端;

2、任何一個客戶,均可以與伺服器進行通訊;

3、伺服器端能及時顯示已串連的用戶端狀態,然後將之告知給所有的用戶端;

4、客戶與伺服器串連成功以後,可以與任何一個其他使用者進行聊天通訊;

5、客戶如果退出程式,伺服器要將之告知其他的客戶。


一、伺服器的設計與編程。

伺服器的設計介面如下所示

伺服器端的代碼如下所示:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;//添加的命名空間using System.Net;using System.Net.Sockets;using System.IO;using System.Threading;namespace WindowsFormsApplication1{    public partial class MainForm : Form    {        //用來儲存串連的使用者        private List<User> userList = new List<User>();        //使用原生IP地址        IPAddress localAddress;        //定義電腦上使用的連接埠號碼        private const int port = 51888;        private TcpListener myListener;        //定義一個標誌,用來判斷是否正常退出所有接受線程        bool isNormalExit = false;        //載入主表單時初始化        public MainForm()        {            InitializeComponent();            listBoxStatus.HorizontalScrollbar = true;            IPAddress[] addrIP = Dns.GetHostAddresses(Dns.GetHostName());            localAddress = addrIP[0];            buttonStop.Enabled = false;        }        //單擊監聽按鈕的處理事件        private void buttonStart_Click(object sender, EventArgs e)        {            myListener = new TcpListener(localAddress, port);            myListener.Start();            AddItemToListBox(string.Format("開始在{0}:{1}監聽客戶串連", localAddress, port));            //建立一個線程監聽用戶端串連請求            Thread myThread = new Thread(ListenClientConnect);            myThread.Start();            buttonStart.Enabled = false;            buttonStop.Enabled = true;                    }        //接收用戶端串連        private void ListenClientConnect()        {            TcpClient newClient = null;            while (true)            {                try                {                    newClient = myListener.AcceptTcpClient();                }                catch                {                    //當單擊“停止監聽”或者退出此表單時AcceptTcpClient()會產生異常,因此利用此異常退出迴圈                    break;                }                User user = new User(newClient);                Thread threadReceive = new Thread(ReceiveData);                threadReceive.Start(user);                userList.Add(user);                AddItemToListBox(string.Format("[{0}]進入", newClient.Client.RemoteEndPoint));                AddItemToListBox(string.Format("當前串連使用者數:{0}", userList.Count));            }        }        private void ReceiveData(object userState)        {            User user = (User)userState;            TcpClient client = user.client;            while (isNormalExit == false)            {                string receiveString = null;                try                {                    //從網路流中讀出字串,此方法會自動判斷字串長度首碼                    receiveString = user.br.ReadString();                }                catch                {                    if (isNormalExit == false)                    {                        AddItemToListBox(string.Format("與[{0}]失去聯絡,已終止接收該使用者資訊", client.Client.RemoteEndPoint));                        RemoveUser(user);                    }                    break;                }                AddItemToListBox(string.Format("來自[{0}]:{1}", user.client.Client.RemoteEndPoint, receiveString));                string[] splitString = receiveString.Split(',');                switch (splitString[0])                {                     case "Login":                        user.userName = splitString[1];                        SendToAllClient(user, receiveString);                        break;                    case "Logout":                        SendToAllClient(user, receiveString);                        RemoveUser(user);                        return;                    case "Talk":                        string talkString = receiveString.Substring(splitString[0].Length + splitString[1].Length + 2);                        AddItemToListBox(string.Format("{0}對{1}說:{2}", user.userName, splitString[1], talkString));                        SendToClient(user, "talk," + user.userName + "," + talkString);                        foreach (User target in userList)                        {                            if (target.userName == splitString[1] && user.userName != splitString[1])                            {                                SendToClient(target, "talk," + user.userName + "," + talkString);                                break;                            }                        }                        break;                    default:                        AddItemToListBox("什麼意思啊:" + receiveString);                        break;                                        }            }        }        private void SendToClient(User user, string message)        {            try            {                //將字串寫入網路流,此方法會自動附加字串長度首碼                user.bw.Write(message);                user.bw.Flush();                AddItemToListBox(string.Format("向[{0}]發送:{1}", user.userName, message));            }            catch            {                AddItemToListBox(string.Format("向[{0}]發送資訊失敗", user.userName));            }        }        //發送資訊給所有客戶,name指定發給哪個使用者,message儲存資訊的內容        private void SendToAllClient(User user, string message)        {            string command = message.Split(',')[0].ToLower();            if (command == "login")            {                for (int i = 0; i < userList.Count; i++)                {                    SendToClient(userList[i], message);                    if (userList[i].userName != user.userName)                    {                        SendToClient(user, "login," + userList[i].userName);                    }                }            }            else if (command == "logout")            {                for (int i = 0; i < userList.Count; i++)                {                    if (userList[i].userName != user.userName)                    {                        SendToClient(userList[i], message);                    }                }            }        }        //移除使用者,user代表指定要刪除的使用者        private void RemoveUser(User user)        {            userList.Remove(user);            user.close();            AddItemToListBox(string.Format("當前串連使用者數:{0}", userList.Count));        }        private delegate void AddItemToListBoxDelegate(string str);        //想ListBox中追加狀態資訊,str儲存要追加的資訊        private void AddItemToListBox(string str)        {            if (listBoxStatus.InvokeRequired)            {                AddItemToListBoxDelegate d = AddItemToListBox;                listBoxStatus.Invoke(d, str);            }            else            {                listBoxStatus.Items.Add(str);                listBoxStatus.SelectedIndex = listBoxStatus.Items.Count - 1;                listBoxStatus.ClearSelected();            }        }        //按下"停止監聽"按鈕的處理事件        private void buttonStop_Click(object sender, EventArgs e)        {            AddItemToListBox("開始停止服務,並依次使使用者退出!");            isNormalExit = true;            for (int i = userList.Count - 1; i >= 0; i--)            {                RemoveUser(userList[i]);            }            myListener.Stop();            buttonStart.Enabled = true;            buttonStop.Enabled = false;        }        //關閉視窗時觸發的事件        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)        {            if (myListener != null)            {                //引發buttonStop的Click事件                buttonStop.PerformClick();            }        }    }}

二、用戶端的設計與編程。

用戶端的設計介面如下所示

用戶端的代碼如下所示:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;//添加的命名空間using System.Net;using System.Net.Sockets;using System.IO;using System.Threading;namespace SyncChatClient{    public partial class MainForm : Form    {        private bool isExit = false;        private TcpClient client;        private BinaryReader br;        private BinaryWriter bw;        public MainForm()        {            InitializeComponent();            Random r = new Random((int)DateTime.Now.Ticks);            textBoxUserName.Text = "user" + r.Next(100, 999);            listBoxOnlineStatus.HorizontalScrollbar = true;        }        //單擊"串連伺服器"按鈕的Click事件        private void buttonConnect_Click(object sender, EventArgs e)        {            buttonConnect.Enabled = false;            try            {                //此處為方便示範,實際使用時要將Dns.GetHostName()改為伺服器網域名稱                client = new TcpClient(Dns.GetHostName(), 51888);                AddTalkMessage("串連成功");            }            catch            {                AddTalkMessage("串連失敗");                buttonConnect.Enabled = true;                return;            }            //擷取網路流            NetworkStream networkStream = client.GetStream();            //將網路流作為二進位讀寫對象            br = new BinaryReader(networkStream);            bw = new BinaryWriter(networkStream);            SendMessage("Login," + textBoxUserName.Text);            Thread threadReceive = new Thread(new ThreadStart(ReceiveData));            threadReceive.IsBackground = true;            threadReceive.Start();        }        //處理接受的伺服器端資料        private void ReceiveData()        {            string receiveString = null;            while (isExit == false)            {                try                {                    //從網路流中讀出字串                    receiveString = br.ReadString();                }                catch                {                    if (isExit == false)                    {                        MessageBox.Show("與伺服器失去聯絡.");                    }                    break;                }                string[] splitString = receiveString.Split(',');                string command = splitString[0].ToLower();                switch (command)                {                     case "login":                        AddOnline(splitString[1]);                        break;                    case "logout":                        RemoveUserName(splitString[1]);                        break;                    case "talk":                        AddTalkMessage(splitString[1] + ":\r\n");                        AddTalkMessage(receiveString.Substring(splitString[0].Length + splitString[1].Length + 2));                        break;                    default:                        AddTalkMessage("什麼意思啊:" + receiveString);                        break;                }            }            Application.Exit();        }        //向伺服器端發送訊息        private void SendMessage(string message)        {            try            {                //將字串寫入網路流,此方法會自動附加字串長度首碼                bw.Write(message);                bw.Flush();            }            catch            {                AddTalkMessage("發送失敗!");            }        }        private delegate void MessageDelegate(string message);        //在richTextBoxTalkInfo中追加聊天資訊        private void AddTalkMessage(string message)        {            if(richTextBoxTalkInfo.InvokeRequired)            {                MessageDelegate d=new MessageDelegate(AddTalkMessage);                richTextBoxTalkInfo.Invoke(d,new Object[]{message});            }            else            {                richTextBoxTalkInfo.AppendText(message+Environment.NewLine);                richTextBoxTalkInfo.ScrollToCaret();            }        }        private delegate void AddOnlineDelegate(string message);        //在listBoxOnlineStatus中添加線上的其他用戶端資訊        private void AddOnline(string userName)        {            if (listBoxOnlineStatus.InvokeRequired)            {                AddOnlineDelegate d = new AddOnlineDelegate(AddOnline);                listBoxOnlineStatus.Invoke(d, new object[] { userName });            }            else            {                listBoxOnlineStatus.Items.Add(userName);                listBoxOnlineStatus.SelectedIndex = listBoxOnlineStatus.Items.Count - 1;                listBoxOnlineStatus.ClearSelected();            }        }        private delegate void RemoveUserNameDelegate(string userName);        //在listBoxOnlineStatus中移除不線上的其他用戶端資訊        private void RemoveUserName(string userName)        {            if (listBoxOnlineStatus.InvokeRequired)            {                RemoveUserNameDelegate d = RemoveUserName;                listBoxOnlineStatus.Invoke(d, userName);            }            else            {                listBoxOnlineStatus.Items.Remove(userName);                listBoxOnlineStatus.SelectedIndex = listBoxOnlineStatus.Items.Count - 1;                listBoxOnlineStatus.ClearSelected();            }        }        private void buttonSend_Click(object sender, EventArgs e)        {            if (listBoxOnlineStatus.SelectedIndex != -1)            {                SendMessage("Talk," + listBoxOnlineStatus.SelectedItem + "," + textBoxSend.Text + "\r\n");                textBoxSend.Clear();            }            else            {                MessageBox.Show("請先在[當前線上]中選擇一個對話者");            }        }        //關閉視窗時觸發的事件        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)        {            if (client != null)            {                SendMessage("Logout," + textBoxUserName.Text);                isExit = true;                br.Close();                bw.Close();                client.Close();            }        }        //在發送資訊文字框中按下【Enter】鍵觸發的事件        private void textBoxSend_KeyPress(object sender, KeyPressEventArgs e)        {            if (e.KeyChar == (char)Keys.Return)            {                buttonSend.PerformClick();            }        }    }}

至此,程式編寫完成。

資源下載連結地址:http://download.csdn.net/detail/scrystally/4730653



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.