面向对象课程大作业要求写一个面向对象设计的工程,所以我选择了网络聊天。
整个项目源码下载地址:http://download.csdn.net/detail/weixingstudio/4301232
具体的分析以后给出,先给出部分代码实现。
这里的实现只有客户端,服务器端下一节给出。
登录窗口的代码:
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 UtilityClass;
using System.Net;
using System.Net.Sockets;
using System.Collections.Specialized;
namespace Client
{
public partial class Login : Form
{
public Login()
{
InitializeComponent();
}
private void button_cancel_Click(object sender, EventArgs e)
{
this.Close();
}
private void button_OK_Click(object sender, EventArgs e)
{
VerifyUserInfo verify = new VerifyUserInfo();
string userName = textBox1.Text.Trim();
string serverIP = textBox2.Text.Trim();
string serverPort = textBox3.Text.Trim();
if (!verify.VerifyUserName(userName))
{
MessageBox.Show("请重新填写用户名!","提示");
textBox1.Focus();
}
else
{
if (!verify.VerifyServerIP(serverIP))
{
MessageBox.Show("请重新填写服务器IP!", "提示");
textBox2.Focus();
}
else
{
if (!verify.VerifyServerPort(serverPort))
{
MessageBox.Show("请重新填写服务器端口!", "提示");
textBox3.Focus();
}
else
{
// 打开聊天窗口
//MessageBox.Show("Good", "提示");
try
{
int serverPort_int=int.Parse(serverPort);
ServerConfig serverConfig = new ServerConfig(serverIP, serverPort_int);
IPAddress serverIPAddress = IPAddress.Parse(serverConfig.ServerIP);
TcpClient client = new TcpClient();
client.Connect(serverIPAddress, serverConfig.ServerPort);
if (client==null)
{
MessageBox.Show("连接服务器失败,请重新填写服务器数据或者查看服务器运行状态!", "提示");
textBox1.Focus();
}
else
{
// 连接成功以后的操作
NetworkStream clientNetWorkStream = client.GetStream();
// 发送用户名
byte[] bytes2beSend=Command.EncodeCommand(userName);
clientNetWorkStream.Write(bytes2beSend, 0, bytes2beSend.Length);
byte[] receiveBuffer=new byte[serverConfig.MaxBuffer];
clientNetWorkStream.Read(receiveBuffer, 0, receiveBuffer.Length);
string connResult = Command.DecodeCommand(receiveBuffer);
if (connResult==Command.RedundantUserName)
{
MessageBox.Show("重复的用户名,请重新填写用户名。", "提示");
}
else if (connResult==Command.ExceedMaxAllowedNumber)
{
MessageBox.Show("超出了服务器最多允许的连接数量,请稍后连接!", "提示");
}
else if (connResult==Command.ConnectConfirm)
{
请求用户列表
开始先请求一个在线用户列表
//byte[] cmd = new byte[serverConfig.MaxBuffer];
//cmd = Command.EncodeCommand(Command.RequestOnlineUser);
//clientNetWorkStream.Write(cmd, 0, cmd.Length);
读取在线用户列表
//clientNetWorkStream.Read(cmd, 0, cmd.Length);
//StringCollection sc = Command.DeserializeOnlineUser(cmd);
// 打开聊天窗口
MainChatFrm mainChat = new MainChatFrm(userName,serverConfig,clientNetWorkStream); // 将数据流传递给另外一个窗口
mainChat.Owner = this;
this.Hide();
mainChat.Show();
}
}
}
catch (System.Exception ex)
{
MessageBox.Show("出错了!远程服务器没有响应。连接服务器失败,请重新填写服务器数据或者查看服务器运行状态!", "提示");
}
}
}
}
}
}
}
主聊天窗口的代码:
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 UtilityClass;
using System.Net.Sockets;
using System.Threading;
using System.Runtime.InteropServices;
using System.Collections.Specialized;
namespace Client
{
public partial class MainChatFrm : Form
{
Thread receiveMegThread;
ServerConfig serverConfig;
NetworkStream networkStream;
string userName;
private bool isDisconnected = false;
private delegate void showMessage(string s);
private delegate void addOnlineUser(string s);
public MainChatFrm()
{
InitializeComponent();
}
public MainChatFrm(string name, ServerConfig config, NetworkStream ns)
{
InitializeComponent();
this.listBox_onlineuser.Items.Clear();
this.userName = name;
this.serverConfig = config;
this.networkStream = ns;
this.label_username.Text += userName;
this.label_serverIP.Text += serverConfig.ServerIP + ":" + serverConfig.ServerPort;
this.richTextBox1.Text += "你好 " + userName + ",欢迎来到微星聊天室! " + DateTime.Now + "\n";
try
{
// 开启接收消息的线程
receiveMegThread = new Thread(new ThreadStart(ReceiveMessage));
receiveMegThread.IsBackground = true;
receiveMegThread.Start();
Thread.Sleep(100);
}
catch (System.Exception ex)
{
//
}
}
/// <summary>
/// 接收消息处理线程函数
/// </summary>
private void ReceiveMessage()
{
try
{
while (true)
{
byte[] receiveBuffer=new byte[serverConfig.MaxBuffer];
networkStream.Read(receiveBuffer, 0, receiveBuffer.Length);
string cmd_from_server = Command.DecodeCommand(receiveBuffer);
switch (cmd_from_server)
{
// 服务器通知有用户上线
case Command.SomeoneConnected:
{
// 获取用户名
byte[] cmd=new byte[serverConfig.MaxBuffer];
networkStream.Read(cmd, 0, cmd.Length);
string name = Command.DecodeCommand(cmd);
if (name!=userName)
{
// 线程安全的添加数据到RichTextBox
AddText2RTB("用户:" + name + " 上线了!" + " " + DateTime.Now);
}
else
{
// nothing
}
// 请求最新的用户列表
cmd = Command.EncodeCommand(Command.RequestOnlineUser);
// 发送请求在线用户列表命令
networkStream.Write(cmd, 0, cmd.Length);
break;
}
// 服务器发送用户列表
case Command.SendOnlinUserList:
{
// 接收数据
networkStream.Read(receiveBuffer, 0, receiveBuffer.Length);
StringCollection sc = Command.DeserializeOnlineUser(receiveBuffer);
ClearOnlineUserList();
ClearComboList();
foreach (string s in sc)
{
// 线程安全的添加数据
AddOnlineUserList(s);
}
break;
}
// 有人离开
case Command.SomeoneLeave:
{
byte[] cmd=new byte[serverConfig.MaxBuffer];
networkStream.Read(cmd, 0, cmd.Length);
string name = Command.DecodeCommand(cmd);
AddText2RTB("用户:" + name + " 离开了系统." + DateTime.Now);
// 线程安全的移除下线的用户
Action<object> call = delegate(object s) { this.listBox_onlineuser.Items.Remove(s);
this.comboBox_selectUser.Items.Remove(s); };
this.listBox_onlineuser.Invoke(call, name);
break;
}
// 有广播消息
case Command.BroadcastAll:
{
// 获取广播消息的用户名
byte[] cmd=new byte[serverConfig.MaxBuffer];
networkStream.Read(cmd, 0, cmd.Length);
string name = Command.DecodeCommand(cmd);
AddText2RTB("用户:" + name + "在" + DateTime.Now + "对大家说:");
byte[] msg=new byte[serverConfig.MaxBuffer];
networkStream.Read(msg, 0, msg.Length);
string message = Command.DecodeCommand(msg);
AddText2RTB(message);
break;
}
// 对这个用户单独发送数据
case Command.SendMessage2One:
{
byte[] cmd = new byte[serverConfig.MaxBuffer];
networkStream.Read(cmd, 0, cmd.Length);
string name_from = Command.DecodeCommand(cmd);
//
Thread.Sleep(20);
networkStream.Read(cmd, 0, cmd.Length);
string message = Command.DecodeCommand(cmd);
AddText2RTB("用户:" + name_from + "在" + DateTime.Now + "对你悄悄的说:");
AddText2RTB(message);
break;
}
// 请求抖动
case Command.VibrateOne:
{
byte[] cmd = new byte[serverConfig.MaxBuffer];
networkStream.Read(cmd, 0, cmd.Length);
string name_from = Command.DecodeCommand(cmd);
AddText2RTB("用户:" + name_from + "在" + DateTime.Now + "给您发送了一个抖动");
Vibrate();
break;
}
case Command.VibrateAll:
{
byte[] cmd = new byte[serverConfig.MaxBuffer];
networkStream.Read(cmd, 0, cmd.Length);
string name_from = Command.DecodeCommand(cmd);
AddText2RTB("用户:" + name_from + "在" + DateTime.Now + "给所有人发送了一个抖动");
Vibrate();
break;
}
case Command.ServerShutdown:
{
AddText2RTB("服务器已经关闭,请退出程序,重新连接服务器。");
this.networkStream.Close();
networkStream=null;
this.button_send.Enabled = false;
break;
}
default:
{
break;
}
}
}
}
catch (System.Exception ex)
{
// 服务器连接失败,清理连接
if (networkStream!=null)
{
MessageBox.Show("服务器连接失败!");
networkStream.Close();
networkStream = null;
}
}
}
private void ClearOnlineUserList()
{
Action call = delegate() { this.listBox_onlineuser.Items.Clear(); };
this.listBox_onlineuser.Invoke(call);
}
private void ClearComboList()
{
Action call = delegate() { this.comboBox_selectUser.Items.Clear(); };
this.comboBox_selectUser.Invoke(call);
}
private void AddOnlineUserList(string user)
{
addOnlineUser call = delegate(string s) { this.listBox_onlineuser.Items.Add(s);
this.comboBox_selectUser.Items.Add(s); };
this.listBox_onlineuser.Invoke(call,user);
}
//private void fromClosed(object sender, FormClosedEventArgs e)
//{
// DisConnectWithServer();
// this.Owner.Close();
// this.Close();
//}
private void button_close_Click(object sender, EventArgs e)
{
if (networkStream != null)
{
DialogResult ret;
ret = MessageBox.Show("确定与服务器断开连接吗?",
"退出",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2);
if (ret == DialogResult.OK)
{
try
{
isDisconnected = true;
// 向服务器发送离线请求
byte[] cmd = Command.EncodeCommand(Command.DisConnect);
networkStream.Write(cmd, 0, cmd.Length);
if (receiveMegThread != null)
{
receiveMegThread.Abort();
}
if (networkStream != null)
{
// 关闭网络流
networkStream.Close();
networkStream.Dispose();
}
this.Owner.Close();
this.Close();
}
catch (System.Exception ex)
{
}
}
}
else
{
this.Owner.Close();
this.Close();
}
}
/// <summary>
/// 与服务器断开连接
/// </summary>
private void DisConnectWithServer()
{
}
[DllImport("user32.dll")]
public static extern bool FlashWindow(IntPtr hWnd, bool bInvert);
/// <summary>
/// 给用户发送抖动
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void pictureBox1_Click(object sender, EventArgs e)
{
if (radioButton_all.Checked)
{
//AddText2RTB("禁止对所有用户发送抖动!");
// 发送命令
byte[] cmd = Command.EncodeCommand(Command.VibrateAll);
networkStream.Write(cmd, 0, cmd.Length);
Thread.Sleep(20);
AddText2RTB("您给所有人发送了一个抖动");
Vibrate();
}
else if (radioButton_one.Checked)
{
// 给当个用户发送抖动
if (this.comboBox_selectUser.SelectedItem==null)
{
MessageBox.Show("请选择一个私聊用户");
}
else
{
string name_private = comboBox_selectUser.SelectedItem.ToString();
if (name_private == userName)
{
MessageBox.Show("您不能给自己发送抖动!");
}
else
{
// 发送命令
byte[] cmd=Command.EncodeCommand(Command.VibrateOne);
networkStream.Write(cmd, 0, cmd.Length);
Thread.Sleep(20);
// 发送抖动用户
cmd = Command.EncodeCommand(name_private);
networkStream.Write(cmd, 0, cmd.Length);
Thread.Sleep(20);
Vibrate();
}
}
}
}
private void Vibrate()
{
if (this.WindowState == FormWindowState.Minimized)
{
FlashWindow(this.Handle, true);
}
Nudge();
}
/// <summary>
/// 产生闪屏振动效果
/// </summary>
private void Nudge()
{
if (this.WindowState == FormWindowState.Minimized)
{
this.WindowState = FormWindowState.Normal;
}
int i = 0;
Point _old = this.Location;
Point _new1 = new Point(_old.X + 2, _old.Y + 2);
Point _new2 = new Point(_old.X - 2, _old.Y - 2);
//_sp2.Play();
while (i < 4)
{
this.Location = _new1;
Thread.Sleep(60);
this.Location = _new2;
Thread.Sleep(60);
i++;
}
this.Location = _old;
}
private void chatFrm_close(object sender, FormClosedEventArgs e)
{
if (!isDisconnected)
{
try
{
if (networkStream != null)
{
DialogResult ret;
ret = MessageBox.Show("确定与服务器断开连接吗?",
"退出",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2);
if (ret == DialogResult.OK)
{
isDisconnected = true;
// 向服务器发送离线请求
byte[] cmd = Command.EncodeCommand(Command.DisConnect);
networkStream.Write(cmd, 0, cmd.Length);
if (receiveMegThread != null)
{
receiveMegThread.Abort();
}
if (networkStream != null)
{
// 关闭网络流
networkStream.Close();
networkStream.Dispose();
networkStream = null;
}
this.Owner.Close();
this.Close();
}
}
else
{
isDisconnected = true;
this.Owner.Close();
this.Close();
}
}
catch (System.Exception ex)
{
//
}
}
}
private void AddText2RTB(string msg)
{
if (this.richTextBox1.InvokeRequired)
{
showMessage call = delegate(string s) { this.richTextBox1.Text += s + "\n"; };
this.richTextBox1.Invoke(call, msg);
}
else
{
this.richTextBox1.Text += msg + "\n";
}
}
/// <summary>
/// 发送用户消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button_send_Click(object sender, EventArgs e)
{
string messsage = this.richTextBox2.Text;
if (Command.VerifyMessage(messsage))
{
// 验证将要发送的消息正确
if (radioButton_all.Checked)
{
// 给所有人发送消息
// 给服务器发送命令
byte[] cmd = Command.EncodeCommand(Command.BroadcastAll);
networkStream.Write(cmd, 0, cmd.Length);
Thread.Sleep(50);
// 发送要传送的数据
cmd = Command.EncodeCommand(messsage);
networkStream.Write(cmd, 0, cmd.Length);
AddText2RTB("你" + "在 " + DateTime.Now + " 对大家说:");
AddText2RTB(messsage);
this.richTextBox2.Text = "";
this.richTextBox2.Focus();
}
else if (radioButton_one.Checked)
{
// 给单个人发送消息
try
{
if (comboBox_selectUser.SelectedItem==null)
{
MessageBox.Show("请选择一个私聊用户");
}
string name_private = comboBox_selectUser.SelectedItem.ToString();
if (name_private == userName)
{
MessageBox.Show("您不能和自己私聊!");
this.richTextBox2.Text = "";
this.richTextBox2.Focus();
}
else
{
// 发送命令
byte[] cmd = Command.EncodeCommand(Command.SendMessage2One);
networkStream.Write(cmd, 0, cmd.Length);
Thread.Sleep(50);
// 发送对象名
cmd = Command.EncodeCommand(name_private);
networkStream.Write(cmd, 0, cmd.Length);
Thread.Sleep(50);
// 发送数据
cmd = Command.EncodeCommand(messsage);
networkStream.Write(cmd, 0, cmd.Length);
AddText2RTB("你" + "在 " + DateTime.Now + " 对 " + name_private + "说:");
AddText2RTB(messsage);
this.richTextBox2.Text = "";
this.richTextBox2.Focus();
}
}
catch (System.Exception ex)
{
//
}
}
}
else
{
this.richTextBox2.Text = "";
this.richTextBox2.Focus();
AddText2RTB("请输入正确的消息然后在发送!!!" + DateTime.Now);
}
}
/// <summary>
/// 清除数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button_clear_Click(object sender, EventArgs e)
{
this.richTextBox2.Text = "";
this.richTextBox2.Focus();
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
this.richTextBox1.SelectionStart = this.richTextBox1.TextLength;
this.richTextBox1.ScrollToCaret();
if (this.WindowState == FormWindowState.Minimized)
{
FlashWindow(this.Handle, true);
}
}
}
}
其中封装了两个在服务器端和客户端工程中都需要使用的配置类和命令类,下一节给出。