using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows;
using ChartClient.Model;
namespace ChartServer
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow
{
/// <summary>
/// 处于连接状态的所有客户端列表
/// </summary>
private readonly List<Users> _userList = new List<Users>();
private TcpListener _listener;
private IPAddress _ip;
bool isNormailExit = false;
public bool isNormalExit { get; set; }
//创建Socket
//Socket client;
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
Closed += MainWindow_Closed;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
_ip = ips[ips.Length - 1];
IpAddress.Text = _ip.ToString();
}
private void MainWindow_Closed(object sender, EventArgs e)
{
//退出监听
if (_listener != null)
{
//停止服务
_listener.Stop();
}
}
/// <summary>
/// 启动服务
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Start_OnClick(object sender, RoutedEventArgs e)
{
//获取IP地址
IPAddress ipAddress = _ip;
//获取端口号
int port = Convert.ToInt32(TbPort.Text);
//绑定socket和端口号
try
{
_listener = new TcpListener(ipAddress, port);
//监听该端口号
_listener.Start();
//发布监听消息
Logs.AppendText(string.Format("服务器:{0} 监听端口:{1} 开始监听 . . .", ipAddress, port) + "\n");
//接收来自客户端的连接请求(线程)
Thread clientConnectThread = new Thread(ListenClientConnect);
//启动监听
clientConnectThread.Start();
Start.IsEnabled = false;
}
catch (Exception ex)
{
Logs.AppendText(ex.Message + "\n");
}
}
/// <summary>
/// 监听来自客户端的连接请求
/// </summary>
/// <param name="obj"></param>
private void ListenClientConnect(object obj)
{
TcpClient thisClient = null;
while (true)
{
try
{
thisClient = _listener.AcceptTcpClient();
}
catch (Exception)
{
break;
}
//每接收一个客户端连接,就创建一个对应的线程循环接收该客户端发来的信息;
Users user = new Users(thisClient);
//从socket 中读取字符
Thread receiveMsgThread = new Thread(ReceiveMsg);
//开启线程
receiveMsgThread.Start(user);
//xxx用户登录成功,当前连接用户数
Logs.AppendText(string.Format("{0}登录系统 ", thisClient.Client.RemoteEndPoint ));
Logs.AppendText(string.Format(" 当前在线用户:{0}", _userList.Count) + "\n");
}
}
/// <summary>
/// 从socket中接收来自客户端的数据
/// </summary>
/// <param name="clientmsg">客户端信息</param>
private void ReceiveMsg(object clientmsg)
{
Users user = (Users)clientmsg;
//获取客户端TcpClient
TcpClient client = user.Client;
while (isNormailExit == false)
{
//从网络中读取字符串
string binaryDatamsg = null;
try
{
//二进制流转字符串
binaryDatamsg = user.BinaryDataReader.ReadString();
}
catch (Exception)
{
if (isNormalExit == false)
{
Logs.AppendText(string.Format("与[{0}]失去联系,已终止接收该用户信息", client.Client.RemoteEndPoint) + "\n");
//将用户移除
RemoveUser(user);
}
break;
}
//记录用户基本操作 如登录、注销、开始会话等
Logs.AppendText(string.Format("来自{0}", user.Client.Client.RemoteEndPoint));
Logs.AppendText(string.Format(" :{0}",binaryDatamsg)+"\n");
string[] splitString = binaryDatamsg.Split(',');
switch (splitString[0])
{
case "Login": //登录
user.Name = splitString[1];
SendToAllClient(user, binaryDatamsg);
break;
case "Logout"://注销
SendToAllClient(user, binaryDatamsg);
RemoveUser(user);
return;
case "Talk":
string talkString = binaryDatamsg.Substring(splitString[0].Length + splitString[1].Length + 2);
Logs.AppendText(string.Format("{0}对{1}说:{2}", user.Name, splitString[1], talkString));
SendToClient(user, "talk," + user.Name + "," + talkString);
foreach (Users target in _userList)
{
if (target.Name == splitString[1] && user.Name != splitString[1])
{
SendToClient(target, "talk," + user.Name + "," + talkString);
break;
}
}
break;
default:
Logs.AppendText("什么意思啊:" + binaryDatamsg);
break;
}
}
}
/// <summary>
/// 发送消息给指定用户
/// </summary>
/// <param name="user"></param>
/// <param name="msg"></param>
private void SendToClient(Users user, string msg)
{
try
{
//将字符串写入网络流,此方法会自动附加字符串长度前缀
user.BinaryDataWriter.Write(msg);
user.BinaryDataWriter.Flush();
Logs.AppendText(string.Format("向[{0}]发送:{1}", user.Name, msg));
}
catch
{
Logs.AppendText(string.Format("向[{0}]发送信息失败", user.Name));
}
}
/// <summary>
/// 发送消息给所有客户端
/// </summary>
/// <param name="user"></param>
/// <param name="binaryData"></param>
private void SendToAllClient(Users user, string message)
{
string command = message.Split(',')[0].ToLower();
if (command == "login")
{
//获取所有客户端在线信息到当前登录用户
for (int i = 0; i < _userList.Count; i++)
{
SendToClient(user, "login," + _userList[i].Name);
}
//把自己上线,发送给所有客户端
for (int i = 0; i < _userList.Count; i++)
{
if (user.Name != _userList[i].Name)
{
SendToClient(_userList[i], "login," + user.Name);
}
}
}
else if (command == "logout")
{
for (int i = 0; i < _userList.Count; i++)
{
if (_userList[i].Name != user.Name)
{
SendToClient(_userList[i], message);
}
}
}
}
/// <summary>
/// 将用户移除
/// </summary>
/// <param name="user"></param>
private void RemoveUser(Users user)
{
_userList.Remove(user);
user.Close();
Logs.AppendText(string.Format("当前连接用户数:{0}", _userList.Count));
}
/// <summary>
/// 停止服务
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Stop_OnClick(object sender, RoutedEventArgs e)
{
//发布通知
Logs.AppendText("服务已停止!" + "\n");
isNormalExit = true;
for (int i = _userList.Count - 1; i >= 0; i--)
{
RemoveUser(_userList[i]);
}
if (_listener != null)
{
//停止服务
_listener.Stop();
}
Start.IsEnabled = true;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows;
using ChartClient.Model;
namespace ChartServer
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow
{
/// <summary>
/// 处于连接状态的所有客户端列表
/// </summary>
private readonly List<Users> _userList = new List<Users>();
private TcpListener _listener;
private IPAddress _ip;
bool isNormailExit = false;
public bool isNormalExit { get; set; }
//创建Socket
//Socket client;
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
Closed += MainWindow_Closed;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
_ip = ips[ips.Length - 1];
IpAddress.Text = _ip.ToString();
}
private void MainWindow_Closed(object sender, EventArgs e)
{
//退出监听
if (_listener != null)
{
//停止服务
_listener.Stop();
}
}
/// <summary>
/// 启动服务
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Start_OnClick(object sender, RoutedEventArgs e)
{
//获取IP地址
IPAddress ipAddress = _ip;
//获取端口号
int port = Convert.ToInt32(TbPort.Text);
//绑定socket和端口号
try
{
_listener = new TcpListener(ipAddress, port);
//监听该端口号
_listener.Start();
//发布监听消息
Logs.AppendText(string.Format("服务器:{0} 监听端口:{1} 开始监听 . . .", ipAddress, port) + "\n");
//接收来自客户端的连接请求(线程)
Thread clientConnectThread = new Thread(ListenClientConnect);
//启动监听
clientConnectThread.Start();
Start.IsEnabled = false;
}
catch (Exception ex)
{
Logs.AppendText(ex.Message + "\n");
}
}
/// <summary>
/// 监听来自客户端的连接请求
/// </summary>
/// <param name="obj"></param>
private void ListenClientConnect(object obj)
{
TcpClient thisClient = null;
while (true)
{
try
{
thisClient = _listener.AcceptTcpClient();
}
catch (Exception)
{
break;
}
//每接收一个客户端连接,就创建一个对应的线程循环接收该客户端发来的信息;
Users user = new Users(thisClient);
//从socket 中读取字符
Thread receiveMsgThread = new Thread(ReceiveMsg);
//开启线程
receiveMsgThread.Start(user);
//xxx用户登录成功,当前连接用户数
Logs.AppendText(string.Format("{0}登录系统 ", thisClient.Client.RemoteEndPoint ));
Logs.AppendText(string.Format(" 当前在线用户:{0}", _userList.Count) + "\n");
}
}
/// <summary>
/// 从socket中接收来自客户端的数据
/// </summary>
/// <param name="clientmsg">客户端信息</param>
private void ReceiveMsg(object clientmsg)
{
Users user = (Users)clientmsg;
//获取客户端TcpClient
TcpClient client = user.Client;
while (isNormailExit == false)
{
//从网络中读取字符串
string binaryDatamsg = null;
try
{
//二进制流转字符串
binaryDatamsg = user.BinaryDataReader.ReadString();
}
catch (Exception)
{
if (isNormalExit == false)
{
Logs.AppendText(string.Format("与[{0}]失去联系,已终止接收该用户信息", client.Client.RemoteEndPoint) + "\n");
//将用户移除
RemoveUser(user);
}
break;
}
//记录用户基本操作 如登录、注销、开始会话等
Logs.AppendText(string.Format("来自{0}", user.Client.Client.RemoteEndPoint));
Logs.AppendText(string.Format(" :{0}",binaryDatamsg)+"\n");
string[] splitString = binaryDatamsg.Split(',');
switch (splitString[0])
{
case "Login": //登录
user.Name = splitString[1];
SendToAllClient(user, binaryDatamsg);
break;
case "Logout"://注销
SendToAllClient(user, binaryDatamsg);
RemoveUser(user);
return;
case "Talk":
string talkString = binaryDatamsg.Substring(splitString[0].Length + splitString[1].Length + 2);
Logs.AppendText(string.Format("{0}对{1}说:{2}", user.Name, splitString[1], talkString));
SendToClient(user, "talk," + user.Name + "," + talkString);
foreach (Users target in _userList)
{
if (target.Name == splitString[1] && user.Name != splitString[1])
{
SendToClient(target, "talk," + user.Name + "," + talkString);
break;
}
}
break;
default:
Logs.AppendText("什么意思啊:" + binaryDatamsg);
break;
}
}
}
/// <summary>
/// 发送消息给指定用户
/// </summary>
/// <param name="user"></param>
/// <param name="msg"></param>
private void SendToClient(Users user, string msg)
{
try
{
//将字符串写入网络流,此方法会自动附加字符串长度前缀
user.BinaryDataWriter.Write(msg);
user.BinaryDataWriter.Flush();
Logs.AppendText(string.Format("向[{0}]发送:{1}", user.Name, msg));
}
catch
{
Logs.AppendText(string.Format("向[{0}]发送信息失败", user.Name));
}
}
/// <summary>
/// 发送消息给所有客户端
/// </summary>
/// <param name="user"></param>
/// <param name="binaryData"></param>
private void SendToAllClient(Users user, string message)
{
string command = message.Split(',')[0].ToLower();
if (command == "login")
{
//获取所有客户端在线信息到当前登录用户
for (int i = 0; i < _userList.Count; i++)
{
SendToClient(user, "login," + _userList[i].Name);
}
//把自己上线,发送给所有客户端
for (int i = 0; i < _userList.Count; i++)
{
if (user.Name != _userList[i].Name)
{
SendToClient(_userList[i], "login," + user.Name);
}
}
}
else if (command == "logout")
{
for (int i = 0; i < _userList.Count; i++)
{
if (_userList[i].Name != user.Name)
{
SendToClient(_userList[i], message);
}
}
}
}
/// <summary>
/// 将用户移除
/// </summary>
/// <param name="user"></param>
private void RemoveUser(Users user)
{
_userList.Remove(user);
user.Close();
Logs.AppendText(string.Format("当前连接用户数:{0}", _userList.Count));
}
/// <summary>
/// 停止服务
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Stop_OnClick(object sender, RoutedEventArgs e)
{
//发布通知
Logs.AppendText("服务已停止!" + "\n");
isNormalExit = true;
for (int i = _userList.Count - 1; i >= 0; i--)
{
RemoveUser(_userList[i]);
}
if (_listener != null)
{
//停止服务
_listener.Stop();
}
Start.IsEnabled = true;
}
}
}