设计一个网络聊天室,能够显示有关该系统基本信息的描述,如:客户端的实例信息、在线等,具体要求如下:
(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;
}
}
///
/// 获取服务器发送过来的数据
///
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;
}
}
///
/// 描述:发送数据到服务器进行处理
///
///
private void sendMsg(string msg)
{
try
{
clientSocket.Send(Encoding.UTF8.GetBytes(msg));
}
catch (Exception ex)
{
showDialog("Error:"+ex.Message);
}
}
#endregion
#region -----------------------2. 发送消息
/// --------------------------------------------
///
/// 描述:发送消息
///
///
///
/// --------------------------------------------
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. 登录
/// --------------------------------------------
///
/// 描述:登录
///
///
///
/// --------------------------------------------
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. 注册
/// --------------------------------------------
///
/// 描述:注册
///
///
///
/// --------------------------------------------
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. 退出
/// --------------------------------------------
///
/// 描述:退出
///
///
///
/// --------------------------------------------
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");
}
/// --------------------------------------------
///
/// 描述:显示弹出框
///
///
/// --------------------------------------------
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 onlineUserName = new List();
public static List onlineSocket = new List();
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