一、首先定义3个全局变量:
在登录窗体FrmLogin.cs定义3个全局变量
- 登录成功和退出的用户Uid (public static string Uid;) --在第三章密码修改功能的时候已经定义了
- 登录成功和退出的时间Time (public static DateTime Time;)
//定义一个全局变量 Uid; 用于获取登录成功后的用户名 public static string Uid;
//定义一个全局变量 Time 用于获取登录成功后的用户的登录时间 public static DateTime Time;
//定义一个登录全局变量 用来获取 "登录" 或是"退出" public static string Situation;
二、将登陆信息赋给全局变量
定义完获取登录的全局变量之后,然后我们需要在判断登录成功后的代码里添加一些代码来获取用户的所有登录信息,并赋给全局变量.
//如果文本框中输入的密码 ==数据库中的密码
if (pwd == txtPwd.Text)
{
//获取登陆成功后的用户ID
Uid = txtName.Text;
//获取当前登录时间
Time = DateTime.Now;
//获取当前用户登录的情况
Situation = "登录";
//说明在该账户下 密码正确, 系统登录成功
MessageBox.Show("系统登录成功,正在跳转主页面...");
FrmMain main = new FrmMain();
main.Show();
this.Hide();
}
三、在登陆成功后将登陆信息写入数据库
public void AddLog()
{
string sql = "insert into Log(User_Name,Situation,Time) values (@User_Name,@Situation,@Time) ";
//简单判断下 插入的数据是否为空 如果为空 则弹出提示
//通常这里不需要(用于异常提示)
if (FrmLogin.Uid == "" || FrmLogin.Situation == "" || FrmLogin.Time.ToString() == "")
{
MessageBox.Show("数据不能为空!");
return;
}
//向数据库里插入参数
SqlParameter[] param ={
new SqlParameter("@User_Name",FrmLogin.Uid),
new SqlParameter("@Situation",FrmLogin.Situation),
new SqlParameter("@Time",FrmLogin.Time)
};
//使用sql连接指令 获取connStr的连接字符串
SqlConnection conn = new SqlConnection(connStr);
//使用cmd指令来装载 sql查询语句和conn连接指令
SqlCommand cmd = new SqlCommand(sql, conn);
//打开数据库
conn.Open();
//向cmd中添加所有参数
cmd.Parameters.AddRange(param);
//将cmd的执行查询获得的整数值赋给n
int n = cmd.ExecuteNonQuery();
//关闭数据库
conn.Close();
}
四、退出登陆
//写一个获取当前系统时间的方法
public void GetExitTime()
{
//获取当前退出系统的时间
FrmLogin.Time = DateTime.Now;
//将当前"退出"字符串赋给登录窗体的全局变量Situation
FrmLogin.Situation = "退出";
}
private void btnExit_Click(object sender, EventArgs e)
{
//调用获取当前退出时间的方法
GetExitTime();
//将当前用户的登录信息添加到DataGridView里面
AddLog();
//直接退出系统
Application.Exit();
}
1、程序分为服务器端和客户端;
2、任何一个客户,均可以与服务器进行通信;
3、服务器端能及时显示已连接的客户端状态,然后将之告知给所有的客户端;
4、客户与服务器连接成功以后,可以与任何一个其他用户进行聊天通讯;
5、客户如果退出程序,服务器要将之告知其他的客户。
一、服务器的设计与编程。
服务器的设计界面如下所示
服务器端的代码如下所示:
<span style="font-size:14px;">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();
}
}
}
}</span>
二、客户端的设计与编程。
客户端的设计界面如下所示
客户端的代码如下所示:
<span style="font-size:14px;">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();
}
}
}
}</span><span style="color:#3333ff; font-size: 18px; "><strong>
</strong></span>
至此,程序编写完成。
资源下载链接地址:http://download.csdn.net/detail/scrystally/4730653