using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
public delegate void DGShowMsg(string strMsg);
namespace Server
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;//关闭跨线程修改控件检查
// txtIP.Text = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0].ToString();
txtIP.Text = Dns.GetHostByName(Dns.GetHostName()).AddressList[0].ToString();
}
[DllImport("kernel32")] ///获取系统时间
public static extern void GetSystemTime(ref SYSTEMTIME_INFO stinfo);
///定义系统时间结构信息
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME_INFO
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
Socket sokWatch = null;//负责监听 客户端段 连接请求的 套接字(女生宿舍的大妈)
Thread threadWatch = null;//负责 调用套接字, 执行 监听请求的线程
//开启监听 按钮
private void btnStartListen_Click(object sender, EventArgs e)
{
//实例化 套接字 (ip4寻址协议,流式传输,TCP协议)
sokWatch
= new Socket
(AddressFamily
.InterNetwork, SocketType
.Stream, ProtocolType
.Tcp);
//创建 ip对象
IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
// IPAddress[] addressList = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
//string ip= this.geta
//创建网络节点对象 包含 ip和port
// IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim())); comboBox1.Text.Trim();
IPEndPoint endpoint
= new IPEndPoint
(address,
int.Parse(comboBox1
.Text.Trim()));
//将 监听套接字 绑定到 对应的IP和端口
sokWatch.Bind(endpoint);
//设置 监听队列 长度为10(同时能够处理 10个连接请求)
sokWatch.Listen(20);
threadWatch
= new Thread
(StartWatch
);
threadWatch.IsBackground = true;
threadWatch.Start();
//txtShow.AppendText("启动服务器成功......rn");
label4.Text = "启动服务器成功......";
}
//Dictionary<string, Socket> dictSocket = new Dictionary<string, Socket>();
Dictionary
<string, ConnectionClient
> dictConn
= new Dictionary
<string, ConnectionClient
>();
bool isWatch = true;
#region 1.被线程调用 监听连接端口
/// <summary>
/// 被线程调用 监听连接端口
/// </summary>
void StartWatch()
{
string recode;
while (isWatch)
{
//threadWatch.SetApartmentState(ApartmentState.STA);
//监听 客户端 连接请求,但是,Accept会阻断当前线程
Socket sokMsg = sokWatch.Accept();//监听到请求,立即创建负责与该客户端套接字通信的套接字
ConnectionClient connection
= new ConnectionClient
(sokMsg, ShowMsg, RemoveClientConnection
);
//将负责与当前连接请求客户端 通信的套接字所在的连接通信类 对象 装入集合
dictConn.Add(sokMsg.RemoteEndPoint.ToString(), connection);
//将 通信套接字 加入 集合,并以通信套接字的远程IpPort作为键
//dictSocket.Add(sokMsg.RemoteEndPoint.ToString(), sokMsg);
//将 通信套接字的 客户端IP端口保存在下拉框里
cboClient.Items.Add(sokMsg.RemoteEndPoint.ToString());
MessageBox.Show("有一个客户端新添加!");
recode = sokMsg.RemoteEndPoint.ToString();
//调用GetSystemTime函数获取系统时间信息
SYSTEMTIME_INFO StInfo
; StInfo
= new SYSTEMTIME_INFO
();
GetSystemTime(ref StInfo);
recode +="子计算机在"+StInfo.wYear.ToString() + "年" + StInfo.wMonth.ToString() + "月" + StInfo.wDay.ToString() + "日";
recode += (StInfo.wHour + 8).ToString() + "点" + StInfo.wMinute.ToString() + "分" + StInfo.wSecond.ToString() + "秒"+"连接服务";
//记录每台子计算机连接服务主机的日志
StreamWriter m_sw
= new StreamWriter
(System.Windows.Forms.Application.StartupPath + @"\file.DAT",
true);
m_sw.WriteLine(recode);
m_sw.WriteLine("------------------------------------------------------------------");
m_sw.Close();
//MessageBox.Show(recode);
dictConn[sokMsg.RemoteEndPoint.ToString()].SendTrue();
//启动一个新线程,负责监听该客户端发来的数据
//Thread threadConnection = new Thread(ReciveMsg);
//threadConnection.IsBackground = true;
//threadConnection.Start(sokMsg);
}
}
#endregion
//bool isRec = true;
//与客户端通信的套接字 是否 监听消息
#region 发送消息 到指定的客户端 -btnSend_Click
//发送消息 到指定的客户端
private void btnSend_Click(object sender, EventArgs e)
{
//byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(txtInput.Text.Trim());
//从下拉框中 获得 要哪个客户端发送数据
string time;
string connectionSokKey = cboClient.Text;
if (!string.IsNullOrEmpty(connectionSokKey))
{
//从字典集合中根据键获得 负责与该客户端通信的套接字,并调用send方法发送数据过去
dictConn[connectionSokKey].Send(txtInput.Text.Trim());
SYSTEMTIME_INFO StInfo
; StInfo
= new SYSTEMTIME_INFO
();
GetSystemTime(ref StInfo);
time = StInfo.wYear.ToString() + "/" + StInfo.wMonth.ToString() + "/" + StInfo.wDay.ToString() +" ";
time += (StInfo.wHour + 8).ToString() + ":" + StInfo.wMinute.ToString();
richTextBox1.AppendText(time + "rn");
richTextBox1.AppendText("对" + cboClient.Text +"说:"+ txtInput.Text.Trim() + "rn");
txtInput.Text = "";
//sokMsg.Send(arrMsg);
}
else
{
MessageBox.Show("请选择要发送的子计算机~~");
}
}
#endregion
//发送闪屏
private void btnShack_Click(object sender, EventArgs e)
{
string connectionSokKey = cboClient.Text;
if (!string.IsNullOrEmpty(connectionSokKey))
{
dictConn[connectionSokKey].SendShake();
}
else
{
MessageBox.Show("请选择要发送的子计算机~~");
}
}
//群闪
private void btnShackAll_Click(object sender, EventArgs e)
{
foreach (ConnectionClient conn in dictConn.Values)
{
conn.SendShake();
}
}
#region 2 移除与指定客户端的连接 +void RemoveClientConnection(string key)
/// <summary>
/// 移除与指定客户端的连接
/// </summary>
/// <param name="key">指定客户端的IP和端口</param>
public void RemoveClientConnection(string key)
{
if (dictConn.ContainsKey(key))
{
dictConn.Remove(key);
MessageBox.Show(key +"断开连接");
cboClient.Items.Remove(key);
}
}
#endregion
//选择要发送的文件
private void btnChooseFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd
= new OpenFileDialog
();
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtFilePath.Text = ofd.FileName;
}
}
//发送文件
private void btnSendFile_Click(object sender, EventArgs e)
{
//拿到下拉框中选中的客户端IPPORT
string key = cboClient.Text;
if (!string.IsNullOrEmpty(key))
{
dictConn[key].SendFile(txtFilePath.Text.Trim());
// txtFilePath.Text = "";
}
else
{
MessageBox.Show("请选择要发送的子计算机~");
}
}
#region 向文本框显示消息 -void ShowMsg(string msgStr)
/// <summary>
/// 向文本框显示消息
/// </summary>
/// <param name="msgStr">消息</param>
public void ShowMsg(string msgStr)
{
//MessageBox.Show("1040414");
txtShow1.AppendText(msgStr + "rn");
}
#endregion
//群消息
private void btnSendMsgAll_Click(object sender, EventArgs e)
{
string time;
foreach (ConnectionClient conn in dictConn.Values)
{
conn.Send(txtInput.Text.Trim());
}
SYSTEMTIME_INFO StInfo
; StInfo
= new SYSTEMTIME_INFO
();
GetSystemTime(ref StInfo);
time = StInfo.wYear.ToString() + "/" + StInfo.wMonth.ToString() + "/" + StInfo.wDay.ToString() + " ";
time += (StInfo.wHour + 8).ToString() + ":" + StInfo.wMinute.ToString();
richTextBox1.AppendText(time + "rn");
richTextBox1.AppendText("群发消息:"+ txtInput.Text.Trim() + "rn");
txtInput.Text = "";
}
//群发文件
private void button1_Click(object sender, EventArgs e)
{
foreach (ConnectionClient conn in dictConn.Values)
{
// dictConn.SendFile(txtFilePath.Text.Trim());
conn.SendFile(txtFilePath.Text.Trim());
}
}
private void button2_Click(object sender, EventArgs e)
{
string connectionSokKey = cboClient.Text;
if (!string.IsNullOrEmpty(connectionSokKey))
{
dictConn[connectionSokKey].guanji();
}
else
{
MessageBox.Show("请选择要发送的子计算机~~");
}
}
private void button3_Click(object sender, EventArgs e)
{
string connectionSokKey = cboClient.Text;
if (!string.IsNullOrEmpty(connectionSokKey))
{
dictConn[connectionSokKey].chongqi();
}
else
{
MessageBox.Show("请选择要发送的子计算机~~");
}
}
private void button4_Click(object sender, EventArgs e)
{
string connectionSokKey = cboClient.Text;
if (!string.IsNullOrEmpty(connectionSokKey))
{
dictConn[connectionSokKey].zhuxiao();
}
else
{
MessageBox.Show("请选择要发送的子计算机~~");
}
}
private void button5_Click(object sender, EventArgs e)
{
string connectionSokKey = cboClient.Text;
if (!string.IsNullOrEmpty(connectionSokKey))
{
dictConn[connectionSokKey].jieping();
}
else
{
MessageBox.Show("请选择要发送的子计算机~~");
}
}
}
///////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////在这里,我新建了一个与客户端的通信和线程的类(ConnectionClient)//////////////////////
/// <summary>
/// 与客户端的 连接通信类(包含了一个 与客户端 通信的 套接字,和线程)
/// </summary>
public class ConnectionClient
{
Socket sokMsg;
DGShowMsg dgShowMsg;//负责 向主窗体文本框显示消息的方法委托
DGShowMsg dgRemoveConnection;// 负责 从主窗体 中移除 当前连接
Thread threadMsg;
#region 构造函数
/// <summary>
///
/// </summary>
/// <param name="sokMsg">通信套接字</param>
/// <param name="dgShowMsg">向主窗体文本框显示消息的方法委托</param>
public ConnectionClient(Socket sokMsg, DGShowMsg dgShowMsg, DGShowMsg dgRemoveConnection)
{
this.sokMsg = sokMsg;
this.dgShowMsg = dgShowMsg;
this.dgRemoveConnection = dgRemoveConnection;
this.threadMsg = new Thread
(RecMsg
);
this.threadMsg.IsBackground = true;
this.threadMsg.Start();
}
#endregion
bool isRec = true;
#region 02负责监听客户端发送来的消息
void RecMsg()
{
while (isRec)
{
try
{
byte[] arrMsg
= new byte[1024 * 1024 * 1];
//接收 对应 客户端发来的消息
int length = sokMsg.Receive(arrMsg);
// string abc = Encoding.Default.GetString(arrMsg);
// MessageBox.Show(abc);
//将接收到的消息数组里真实消息转成字符串
if (arrMsg[0] == 1)
{
//string abc = Encoding.Default.GetString(arrMsg);
//MessageBox.Show(abc);
//发送来的是文件
//MessageBox.Show("00000s");
//SaveFileDialog sfd = new SaveFileDialog();
SaveFileDialog sfd
= new SaveFileDialog
();
sfd.Filter = "文本文件(.txt)|*.txt|所有文件(*.*)|*.*";
// MessageBox.Show(sfd.Filter);
//sfd.ShowDialog();
//弹出文件保存选择框
if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
//MessageBox.Show("111110");
//创建文件流
using (FileStream fs
= new FileStream
(sfd
.FileName, FileMode
.OpenOrCreate))
{
fs.Write(arrMsg, 1, length - 1);
MessageBox.Show("文件保存成功!");
}
}
}
/*else if(arrMsg[0] == 2)
{
// MemoryStream ms = new MemoryStream(arrMsg, 0, length-1);
MemoryStream ms = new MemoryStream(arrMsg);
Image returnImage = Image.FromStream(ms);//??????????
PictureBox district = (PictureBox)Application.OpenForms["Form1"].Controls["pictureBox1"].Controls["pictureBox1"];
district.Image = returnImage;
// this.saveFileDialog1.FileName = "";//清空名称栏
/*
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "图像文件(.jpg)|*.jpg|所有文件(*.*)|*.*";
MessageBox.Show(sfd.Filter);
if (DialogResult.OK == sfd.ShowDialog())
{
string strFileName = sfd.FileName;
//Image img = (Image)this.pictureBox1.Image;
returnImage.Save(strFileName);
}
}*/
else//发送来的是消息
{
//MessageBox.Show("2222");
string strMsg = sokMsg.RemoteEndPoint.ToString()+"说:"+"rn"+System.Text.Encoding.UTF8.GetString(arrMsg, 0, length); //// 我在这里 Request.ServerVariables.Get("Remote_Addr").ToString()+
//通过委托 显示消息到 窗体的文本框
dgShowMsg(strMsg);
}
//MessageBox.Show("11111");
}
catch (Exception ex)
{
isRec = false;
//从主窗体中 移除 下拉框中对应的客户端选择项,同时 移除 集合中对应的 ConnectionClient对象
dgRemoveConnection(sokMsg.RemoteEndPoint.ToString());
}
}
}
#endregion
#region 03向客户端发送消息
/// <summary>
/// 向客户端发送消息
/// </summary>
/// <param name="strMsg"></param>
public void Send(string strMsg)
{
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
byte[] arrMsgFinal
= new byte[arrMsg
.Length + 1];
arrMsgFinal[0] = 0;//设置 数据标识位等于0,代表 发送的是 文字
arrMsg.CopyTo(arrMsgFinal, 1);
sokMsg.Send(arrMsgFinal);
}
#endregion
#region 04向客户端发送文件数据 +void SendFile(string strPath)
/// <summary>
/// 04向客户端发送文件数据
/// </summary>
/// <param name="strPath">文件路径</param>
public void SendFile(string strPath)
{
//通过文件流 读取文件内容
//MessageBox.Show("12540");
using (FileStream fs
= new FileStream
(strPath, FileMode
.OpenOrCreate))
{
byte[] arrFile
= new byte[1024 * 1024 * 2];
//读取文件内容到字节数组,并 获得 实际文件大小
int length = fs.Read(arrFile, 0, arrFile.Length);
//定义一个 新数组,长度为文件实际长度 +1
byte[] arrFileFina
= new byte[length
+ 1];
arrFileFina[0] = 1;//设置 数据标识位等于1,代表 发送的是文件
//将 文件数据数组 复制到 新数组中,下标从1开始
//arrFile.CopyTo(arrFileFina, 1);
Buffer.BlockCopy(arrFile, 0, arrFileFina, 1, length);
// MessageBox.Show("120");
//发送文件数据
sokMsg.Send(arrFileFina);//, 0, length + 1, SocketFlags.None);
}
}
#endregion
#region 05向客户端发送闪屏
/// <summary>
/// 向客户端发送闪屏
/// </summary>
/// <param name="strMsg"></param>
public void SendShake()
{
byte[] arrMsgFinal
= new byte[1];
arrMsgFinal[0] = 2;
sokMsg.Send(arrMsgFinal);
}
#endregion
#region 06关闭与客户端连接
/// <summary>
/// 关闭与客户端连接
/// </summary>
public void CloseConnection()
{
isRec = false;
}
#endregion
#region 07向客户端发送连接成功提示
/// <summary>
/// 向客户端发送连接成功提示
/// </summary>
/// <param name="strMsg"></param>
public void SendTrue()
{
byte[] arrMsgFinal
= new byte[1];
arrMsgFinal[0] = 3;
sokMsg.Send(arrMsgFinal);
}
#endregion
#region 08向客户端发送关机命令
/// <summary>
/// 向客户端发送关机命令
/// </summary>
/// <param name="strMsg"></param>
public void guanji()
{
byte[] arrMsgFinal
= new byte[1];
arrMsgFinal[0] = 4;
sokMsg.Send(arrMsgFinal);
}
#endregion
#region 09向客户端发送重启命令
/// <summary>
/// 向客户端发送关机命令
/// </summary>
/// <param name="strMsg"></param>
public void chongqi()
{
byte[] arrMsgFinal
= new byte[1];
arrMsgFinal[0] = 5;
sokMsg.Send(arrMsgFinal);
}
#endregion
#region 10向客户端发送待机命令
/// <summary>
/// 向客户端发送关机命令
/// </summary>
/// <param name="strMsg"></param>
public void zhuxiao()
{
byte[] arrMsgFinal
= new byte[1];
arrMsgFinal[0] = 6;
sokMsg.Send(arrMsgFinal);
}
#endregion
#region 11向客户端发送截屏命令
/// <summary>
/// 向客户端发送截屏命令
/// </summary>
/// <param name="strMsg"></param>
public void jieping()
{
byte[] arrMsgFinal
= new byte[1];
arrMsgFinal[0] = 7;
sokMsg.Send(arrMsgFinal);
}
#endregion
}
}
//csharp/6777