大二课设-基于Tcp的c/s模式的网络聊天室(c#)

1 篇文章 0 订阅
本文详细描述了一个网络聊天室的设计过程,包括创建服务器端、客户端,实现TCP通讯连接,私聊功能,以及用户登录验证、在线信息展示。系统采用文本文件存储用户信息,涉及账号密码验证、在线列表管理和消息转发机制。
摘要由CSDN通过智能技术生成

设计一个网络聊天室,能够显示有关该系统基本信息的描述,如:客户端的实例信息、在线等,具体要求如下:

(1)聊天室服务器端的创建

(2)聊天室客户端的创建

(3)实现客户与服务器的连接通讯

(4)实现客户之间的私聊

(5)实现客户端的在线信息显示

该系统用户信息存储在文本文件中,当客户端启动时,客户端发送客户输入的账号和密码到服务端,服务端将客户端发送的账号与密码与文件中的信息对比,若成功,将第二个|后面的字符串改为succeed, 由客户端审核第二个|后的字符串是否succed, 若是在将用户名进行判断,判断在线客户列表中是否已经有该名字,若有就显示登录失败,若无,则进入聊天模式,在线客户列表加入此用户

通过套字节设置,采用TCP通讯,用户选择发送对象为ALL,点击发送,系统将信息从客户端发送到服务端,服务端将信息发送到当前在线的所有用户

 

点击刷新在人数,获取在线用户列表,并更新在线人数,刷新在线人数

 

 

客户端

当前客户端UI设计将登录界面和聊天界面合二为一,整体大都采用蓝色,风格简洁,字体为”字魂110号-武林江湖体, 9pt”,整体用户在确认服务端开启且未登录的情况下,用户只能使用登录界面的控件,待用户登录成功后,登录界面的控件设为只读模式

 服务端

服务端页面整体色调为蓝色,包括IP地址,端口的显示,可以显示在线人数,以及连接信息,点击刷新在线人数,可以显示当前在线人数

 

用户数据存储方式

本系统采用的是文本文件的方式存储用户,存储路径为:”C:\Users\黄**\Desktop\课程设计\ChatRoom-master\可执行文件\user”, 文件地址显示如图4-1-1所示。

 源码:

客户端部分:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using Newtonsoft.Json;

namespace ChatRoom.Client
{
    public partial class ClientForm : Form
    {
        //string rs;
        public ClientForm()
        {
            showMsg = new ShowMsg(appendMsg);
            addItem = new AddItem(addItemToComboBox);
            deleteItem = new DeleteItem(deleteItemFromComboBox);
            InitializeComponent();
        }

        #region -----------------------1. Socket处理
        IPAddress address = null;
        Socket clientSocket = null;
        IPEndPoint endPoint = null;
        private void connecToServer()
        {
            try
            {
                //创建客户端套接字
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                address = IPAddress.Parse("127.0.0.1");
                endPoint = new IPEndPoint(address, 9000);
                //连接服务器
                clientSocket.Connect(endPoint);
            }
            catch (Exception e)
            {
                string errStr = string.Format("系统提示:出现了错误!\r\n错误信息:{0}\r\n", e.Message);
                textBox_CLIENT_MSG.AppendText(errStr);
                return;
            }
        }
        /// <summary>
        /// 获取服务器发送过来的数据
        /// </summary>
        private string recvMsg()
        {
            try
            {
                byte[] receveMsg = new byte[1024 * 1024 * 2];
                int length = clientSocket.Receive(receveMsg);
                return Encoding.UTF8.GetString(receveMsg, 0, length);
            }
            catch (Exception e)
            {
                return e.Message;
            }
        }
        /// <summary>
        /// 描述:发送数据到服务器进行处理
        /// </summary>
        /// <param name="msg"></param>
        private void sendMsg(string msg)
        {
            try
            {
                clientSocket.Send(Encoding.UTF8.GetBytes(msg));
            }
            catch (Exception ex)
            {
                showDialog("Error:"+ex.Message);
            }
        }
        #endregion 

        #region -----------------------2. 发送消息
        /// --------------------------------------------
        /// <summary>
        /// 描述:发送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// --------------------------------------------
        private void button_SEND_Click(object sender, EventArgs e)
        {
            try
            {
                //连接服务器成功发送消息
                string msg = textBox_CLIENT_SEND_MSG.Text.ToString();
                string logininUser = textBox_hide.Text;
                if (string.IsNullOrEmpty(logininUser))
                {
                    showDialog("您还没登录");
                    return;
                }
                if (string.IsNullOrEmpty(msg))
                {
                    showDialog("发送内容不能为空");
                    return;
                }
                string toUser = comboBox_USER_LIST.Text.ToString();
                if (string.IsNullOrEmpty(toUser))
                {
                    showDialog("请选择发送对象!");
                    return;
                }
                string sendStrMsg = "Talk|" + textBox_hide.Text.ToString() + "|" + toUser + "|" + msg;
              
                sendMsg(sendStrMsg);
               // sendMsg(rs);         
                textBox_CLIENT_SEND_MSG.Text = "";
                textBox_CLIENT_MSG.AppendText("\r\n"+"你对" + toUser + "说:" + msg +"\r\n");
            }
            catch (Exception ex)
            {
                //出现异常,如:没有连接到服务器
                string errorMsg = string.Format(@"发送失败:{0}", ex.Message);
                textBox_CLIENT_MSG.AppendText(errorMsg + "\r\n");
            }
        }
        #endregion

        #region -----------------------3. 登录
        /// --------------------------------------------
        /// <summary>
        /// 描述:登录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// --------------------------------------------
        private void button_Login_Click(object sender, EventArgs e)
        {

            string username = textBox_UserName.Text.ToString();
            string pwd = textBox_Pwd.Text.ToString();
            if (!checkInput(username, pwd)) return;
            connecToServer();
            string requestLoginMsg = string.Format(@"Login|{0}|{1}", username, pwd);
            try
            {
                sendMsg(requestLoginMsg);
                //初始化登录
                initLogin();
            }
            catch (Exception ex)
            {
                showDialog("登录失败");
                return;
            }
        }
        private void initLogin()
        {
            string strRecvMsg = recvMsg();
            string[] strArray = strRecvMsg.Split('|');
            switch (strArray[0])
            { 
                case "login":
                    if (strArray[1].Equals("succeed"))
                    {
                        string user = textBox_UserName.Text;
                        button_Login.Dispose();
                        button_Register.Dispose();
                        textBox_Pwd.Dispose();
                        textBox_UserName.Dispose();
                        label2.Dispose();
                        label3.Dispose();
                        label_hide.Show();
                        textBox_hide.Text = user;
                        textBox_hide.Show();
                        //启动客户端与服务器的连接服务
                        new ClientService(clientSocket, this);
                        string strSendMsg = "Init|online";
                        sendMsg(strSendMsg);
                    }
                    break;
                case "warning":
                    string warningMsg = this.recvMsg();
                    showDialog(warningMsg.Split('|')[1]);
                    clientSocket.Shutdown(SocketShutdown.Both);
                    clientSocket.Close();
                    clientSocket = null;
                    break;
            }
        }
        #endregion

        #region -----------------------4. 注册
        /// --------------------------------------------
        /// <summary>
        /// 描述:注册
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// --------------------------------------------
        private void button_Register_Click(object sender, EventArgs e)
        {
            string username = textBox_UserName.Text.ToString();
            string pwd = textBox_Pwd.Text.ToString();
            if (!checkInput(username, pwd)) return;
            connecToServer();
            string requestRegMsg = string.Format(@"Reg|{0}|{1}", username, pwd);
            try
            {
                sendMsg(requestRegMsg);
                initLogin();
            }
            catch (Exception ex)
            {
                showDialog("注册失败");
                return;
            }
        }
        #endregion

        #region -----------------------5. 退出
        /// --------------------------------------------
        /// <summary>
        /// 描述:退出
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// --------------------------------------------
        private void button_Cancel_Click(object sender, EventArgs e)
        {
            string msg = "Close|" + textBox_hide.Text;
            sendMsg(msg);
            Application.Exit();
        }
        #endregion

        public void addItemToComboBox(string str)
        {
            //首先移除所有的列表
            comboBox_USER_LIST.Items.Clear();
            comboBox_USER_LIST.Items.Add("All");
            string[] strArray = str.Split('|');
            int i ;
            for ( i = 1; i < strArray.Length; i++)
            {
                if (strArray[1].Equals("0")) return;
                comboBox_USER_LIST.Items.Add(strArray[i]);
            }
           
        }
        public void deleteItemFromComboBox(string who)
        {
            comboBox_USER_LIST.Items.Remove(who);
        }

        #region -----------------------6. 定义委托,子线程中能够像消息列表中添加信息
        delegate void ShowMsg(string msg);
        delegate void AddItem(string msg);
        delegate void DeleteItem(string who);
        ShowMsg showMsg;
        AddItem addItem;
        DeleteItem deleteItem;
        public void DisplayMsg(string msg)
        {
            try
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(showMsg, msg);
                }
            }
            catch (Exception e) { }
        }
        public void addItemToList(string msg)
        {
            try
            {
                if(this.InvokeRequired)
                {
                    this.Invoke(addItem, msg);
                }
            }
            catch (Exception e)
            {}
        }
        public void removeFromToList(string who)
        {
            try
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(deleteItem, who);
                }
            }
            catch (Exception e) { }
        }
        private void appendMsg(string msg)
        {
            textBox_CLIENT_MSG.AppendText(msg + "\n");
        }
        /// --------------------------------------------
        /// <summary>
        /// 描述:显示弹出框
        /// </summary>
        /// <param name="msg"></param>
        /// --------------------------------------------
        private void showDialog(string msg)
        {
            MessageBox.Show(msg);
        }
        #endregion

        #region -----------------------8. 工具方法
        private bool checkInput(string username, string pwd)
        {
            if (string.IsNullOrEmpty(username))
            {
                showDialog("用户名不能为空");
                return false;
            }
            if (string.IsNullOrEmpty(pwd))
            {
                showDialog("密码不能为空");
                return false;
            }
            return true;
        }
        #endregion

        private void comboBox_USER_LIST_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void ClientForm_Load(object sender, EventArgs e)
        {

        }
    }
}

服务器部分代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.IO;
using System.Net.Sockets;
using System.Data.SqlClient;
using System.Data;
namespace ChatRoom.Server
{
    public class ClientConnection
    {
        
        Thread threadClient = null;
        Socket socket = null;
        ServerForm serverForm = null;
        //在线用户的用户名集合和Socket集合
        public static List<string> onlineUserName = new List<string>();
        public static List<Socket> onlineSocket = new List<Socket>();
        public ClientConnection(ServerForm serverForm, Socket socket)
        {
            this.serverForm = serverForm;
            this.socket = socket;
            threadClient = new Thread(watchMsg);
            threadClient.IsBackground = true;
            threadClient.Start();
        }

        #region -------------------------------------1. 实现服务器与客户端的通信
        private void watchMsg()
        {
            try
            {
                while (true)
                {
                    if (socket == null) break;
                    byte[] byteMsgRec = new byte[1024 * 1024 * 4];
                    int length = socket.Receive(byteMsgRec, byteMsgRec.Length, SocketFlags.None);
                    if (length > 0)
                    {
                        string strMsgRec = Encoding.UTF8.GetString(byteMsgRec, 0, length);
                        handleMsg(strMsgRec);
                    }
                }
            }
            catch (Exception e)
            {
                ShowMsg("出现异常:" + e.Message + "\n");
                return;
            }
        }
        //服务器端向客户端发送消息
        public void SendMsg(string msg)
        {
            try
            {
                byte[] msgSendByte = Encoding.UTF8.GetBytes(msg);
                socket.Send(msgSendByte);
            }
            catch (Exception ex)
            {
                ShowMsg("发送消息错误:" + ex.Message + "\n");
                return;
            }
        }
        #endregion
        #region ----------------------------------------2. 处理转发用户消息
        //处理收到的请求,进行转发
        private void handleMsg(string msg)
        {
            string[] strArray = msg.Split('|');
            switch (strArray[0])
            {
                case "Login":
                    login(msg);
                    break;
                case "Init":
                    notifyAll();
                    break;
                case "Reg":
                    register(msg);
                    break;
                case "Talk":
                    talk(msg);
                    break;
                case "Close":
                    close(msg);
                    break;
                default:

                    break;
            }
        }
        //登录
        private void login(string msg)
        {
            string[] strArray = msg.Split('|');
            string userInfo = "";
            for (int i = 1; i < strArray.Length; i++)
            {
                userInfo += strArray[i] + "|";
            }
            userInfo = userInfo.Remove(userInfo.LastIndexOf('|'), 1);
            if (isLoginSucceed(userInfo))
            {
                string username = userInfo.Split('|')[0];
                onlineUserName.Add(username);
                onlineSocket.Add(this.socket);
                ShowMsg(username + ":加入房间" + "\n");
                string feedBack = "login|succeed";
                SendMsg(feedBack);
            }
            else
            {
                string errorMsg = "warning|登录失败";
                SendMsg(errorMsg);
                this.closeSocket();
            }
        }
        //注册
        private void register(string msg)
        {
            string[] strArray = msg.Split('|');
            string userInfo = "";
            for (int i = 1; i < strArray.Length; i++)
            {
                userInfo += strArray[i] + "|";
            }
            userInfo = userInfo.Remove(userInfo.LastIndexOf('|'), 1);
            if (isRegisterSucceed(userInfo))
            {
                string username = userInfo.Split('|')[0];
                onlineUserName.Add(username);
                onlineSocket.Add(this.socket);
                ShowMsg(username + ":加入房间" + "\n");
                string feedBack = "login|succeed";
                SendMsg(feedBack);
            }
            else
            {
                string feedBack = string.Format(@"warning|登录失败!");
                SendMsg(feedBack);
                this.closeSocket();
            }
        }
        //请求在线用户
        private void notifyAll()
        {
            string feedBack = "online";
            if (onlineUserName.Count > 0)
            {
                for (int i = 0; i < onlineUserName.Count; i++)
                {
                    feedBack += "|" + onlineUserName[i];
                }
            }
            else
            {
                feedBack += "|0";
            }

            if (onlineSocket.Count > 0 && onlineUserName.Count > 0)
            {
                for (int i = 0; i < onlineSocket.Count; i++)
                {
                    onlineSocket[i].Send(Encoding.UTF8.GetBytes(feedBack));
                }
            }
        }
        //聊天
        private void talk(string msg)
        {
            string[] strArray = msg.Split('|');
            //消息来自
            string fromUser = strArray[1];
            //消息发送给
            string toUser = strArray[2];
            string msgInfo = strArray[3];
            if (toUser.Equals("All"))
                sendToAll(fromUser, msgInfo);
            else
                sendToUserByName(fromUser, toUser, msgInfo);
        }
        //关闭
        private void close(string msg)
        {
            int length = onlineSocket.Count;
            string[] strArray = msg.Split('|');
            //消息来自
            string fromUser = strArray[1];
            for (int i = 0; i < length; i++)
            {
                if (fromUser.Equals(onlineUserName[i]))
                {
                    onlineUserName.Remove(fromUser);
                    Socket scoket = onlineSocket[i];
                    onlineSocket.Remove(scoket);
                    break;
                }
            }
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            socket = null;
            ShowMsg("提示:"+fromUser+"离开聊天室");
            length = onlineSocket.Count;
            if (onlineSocket.Count > 0)
            {
                for (int i = 0; i < length; i++)
                {
                    string sendMsg = string.Format(@"Close|{0}", fromUser);
                    onlineSocket[i].Send(Encoding.UTF8.GetBytes(sendMsg));
                }
            }
        }

        private void sendToAll(string fromUser, string msg)
        {
            if (onlineUserName.Count > 0 && onlineSocket.Count > 0)
            {
                for (int i = 0; i < onlineSocket.Count; i++)
                {
                    string sendMsg = string.Format("talk|{0}:{1}", fromUser, msg);
                    onlineSocket[i].Send(Encoding.UTF8.GetBytes(sendMsg));
                }
            }
        }
        private void sendToUserByName(string fromUser, string toUser, string msg)
        {
            string sendMsg = string.Format(@"talk|{0}:{1}", fromUser, msg);
            if (onlineSocket.Count > 0 && onlineUserName.Count > 0)
            {
                for (int i = 0; i < onlineUserName.Count; i++)
                {
                    if (toUser.Equals(onlineUserName[i]))
                    {
                        onlineSocket[i].Send(Encoding.UTF8.GetBytes(sendMsg));
                        return;
                    }
                }
            }
        }
        private bool isRegisterSucceed(string strInfo)
        {
            StreamReader streamReader = new StreamReader("User.txt");
            String line = "";
            while ((line = streamReader.ReadLine()) != null)
            {
                if (line.Equals(strInfo)) return false;
            }
            streamReader.Close();
            FileStream fileStream = new FileStream("User.txt", FileMode.Append);
            StreamWriter writer = new StreamWriter(fileStream);
            writer.WriteLine(strInfo);
            writer.Close();
            fileStream.Close();
            return true;
        }
        
        
        private bool isLoginSucceed(string userInfo)//靠文件判断的关键
        {

            StreamReader streamReader = new StreamReader("User.txt");
            string line = "";
            while ((line = streamReader.ReadLine()) != null)
            {
                if (line == userInfo && !onlineUserName.Contains(userInfo.Split('|')[0]))
                    return true;
            }
            streamReader.Close();
            return false;
       
        }
        private void closeSocket()
        {
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            socket = null;
        }
        #endregion
        #region --------------------------------------2. 显示异常信息
        private void ShowMsg(string msg)
        {
            this.serverForm.AppendMsg(msg);
        }
        #endregion
    }
}

github源码:https://github.com/helloword22333/chat-rooms

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学徒在修行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值