在好例子网,分享、交流、成长!
您当前所在位置:首页C# 开发实例C#网络编程 → 通过socket对多台PC远程关机/重启

通过socket对多台PC远程关机/重启

C#网络编程

下载此实例
  • 开发语言:C#
  • 实例大小:0.17M
  • 下载次数:59
  • 浏览次数:454
  • 发布时间:2021-09-11
  • 实例类别:C#网络编程
  • 发 布 人:yuguangsheng
  • 文件格式:.rar
  • 所需积分:15

实例介绍

【实例简介】

Socket服务端功能要求:
1.软件不能被误操作关闭,禁用右上角关闭按钮,可在任务栏右下角图标上点右键关闭,并且弹窗确认。
2.开机自启动,软件启动时就启动Socket服务。
3.界面上显示实时已连接的客户端的IP,端口号和工位名称。
4.可选择客户端单独发送关机、重启指令,也可群发关机指令,全部关机有密码输入弹窗。
5.在配置文件里配置绑定的本机IP和端口号,以及所有工位名称与IP的键值对。
6.软件界面有Socket服务已启动,正在监听中的实时状态指示灯。
7.服务端关闭,不影响客户端运行,客户端正常断开,服务端再打开,客户端正常连接。
8.网线断开(IP不对,防护墙/杀软拦截),不影响服务端运行,客户端端正常断开,网线再连上,客户端正常再连接。
Socket客户端功能要求:
1.软件不能被误操作关闭,禁用右上角关闭按钮,可在任务栏右下角图标上点右键关闭,并且弹窗确认。
2.开机自启动,软件启动时就连接Socket服务端。
3.界面上显示所连接服务端的IP,端口号。客户端启动时默认最小化界面,不耽误操作其他软件。
4.在配置文件里配置要连接的目标服务端IP和端口号,
5.软件界面有已连接Socket服务端的实时状态指示灯,断开连接后每隔2秒自动重连,直到连接上为止,
连接了就不能再重连。
6.客户端关机前弹个窗,提示即将关机。
7.客户端关闭,不影响服务端运行,客户端正常断开,客户端再打开,客户端正常连接。
8.网线断开(IP不对,防护墙/杀软拦截),不影响客户端运行,客户端正常断开,网线再连上,客户端正常再连接。

【实例截图】

from clipboardfrom clipboard


【核心代码】

using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace SocketTestServer
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;//消除对textbox控件的线程检测

            txtIP.Text = ReadConfigFile("ipAddress");
            txtPort.Text = ReadConfigFile("port");


            //软件启动时创建服务
            try
            {

                IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
                IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));//第一步:用指定的端口号和服务器的ip建立一个EndPoint对像
                socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//第二步:建立一个Socket对像
                socketWatch.Bind(endpoint);//第三步:用socket对像的Bind()方法绑定EndPoint
                socketWatch.Listen(100);//第四步:用socket对像的Listen()方法开始监听(挂起连接池的最大长度,提前准备100个挂起的连接,提高高并发性能)
                threadWatch = new Thread(WatchConnection);//创建Socket服务器线程
                threadWatch.IsBackground = true;//设置为后台线程,窗体关闭线程可随之关闭
                threadWatch.Start();
                ShowMsg("Socket服务器启动监听成功......");
                label3.Text = "服务已启动,正在监听中";
                label3.BackColor = Color.Green;
                label3.ForeColor = Color.White;
            }
            catch (Exception ex)
            {
                ShowMsg2(ex.ToString());

            }

        }

        //获取Configuration对象
        Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

        /// <summary>
        /// 根据Key读取配置文件中元素的Value
        /// </summary>
        /// <param name="keyName"></param>
        /// <returns></returns>
        public string ReadConfigFile(string keyName)
        {
            try
            {
                //根据Key读取元素的Value
                string name = config.AppSettings.Settings[keyName].Value;
                //Form1.form1.ReadLog("配置参数" keyName "读取成功");
                ShowMsg("配置参数" keyName "读取成功");
                return name;
            }
            catch (Exception ex)
            {
                ShowMsg2("配置参数" keyName "读取失败");
                return null;
            }
        }





        Thread threadWatch = null;
        Socket socketWatch = null;

        /// <summary>
        /// 创建服务
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {

                IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
                IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));//第一步:用指定的端口号和服务器的ip建立一个EndPoint对像
                socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//第二步:建立一个Socket对像
                socketWatch.Bind(endpoint);//第三步:用socket对像的Bind()方法绑定EndPoint
                socketWatch.Listen(100);//第四步:用socket对像的Listen()方法开始监听(挂起连接池的最大长度,提前准备100个挂起的连接,提高高并发性能)
                threadWatch = new Thread(WatchConnection);//创建Socket服务器线程
                threadWatch.IsBackground = true;//设置为后台线程,窗体关闭线程可随之关闭
                threadWatch.Start();
                ShowMsg("Socket服务器启动监听成功......");
                label3.Text = "服务已启动,正在监听中";
                label3.BackColor = Color.Green;
                label3.ForeColor = Color.White;
            }
            catch (Exception ex)
            {
                ShowMsg2(ex.ToString());

            }
        }

        //定义2个字典
        Dictionary<string, Socket> dictSocket = new Dictionary<string, Socket>();
        Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();

        /// <summary>
        /// 监听客户端请求连接的方法(线程方法),每监听到一个连接,就创建一个线程为该连接进行处理,实现Socket监听多个连接
        /// </summary>
        /// <param name="obj"></param>
        private void WatchConnection(object obj)
        {
            while (true)
            {
                // 负责通信的套接字
                Socket sokConnection = socketWatch.Accept();//第五步:监听客户端的连接,用socket对像的Accept()方法创建新的socket对像和请求的客户端通信(没有新连接时线程就等在这里)
                string online_ipandport = sokConnection.RemoteEndPoint.ToString();
                string online2_ip = online_ipandport.Substring(0, online_ipandport.LastIndexOf(":"));
                string online3_workposition= ReadConfigFile(online2_ip);
                lb_Online.Items.Add(online_ipandport "|" online3_workposition);//加入在线列表控件显示
                dictSocket.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection);//加入通信套接字集合

                //创建通信线程
                Thread thr = new Thread(RecMsg);//每监听到一个连接,就创建一个线程为该连接处理收发数据,实现Socket监听多个连接
                thr.IsBackground = true;
                thr.Start(sokConnection);//注意传入RecMsg方法Accept()来的套接字对象
                dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr);//加入通信线程集合

                ShowMsg("客户端连接成功......" sokConnection.RemoteEndPoint.ToString());
            }
        }

        /// <summary>
        /// 监听客户端发送消息的方法(线程方法)
        /// </summary>
        void RecMsg(object socketClient)
        {
            Socket socketClients = socketClient as Socket;
            while (true)
            {
                byte[] arrMsgRec = new byte[1024 * 1024 * 2];//大小为2Mb的字节数组

                int length = -1;
                try
                {
                    length = socketClients.Receive(arrMsgRec);//第六步,用socket对像的Receive()接收数据放到字节数组中,没有新数据时线程就等在这里
                }
                catch (SocketException ex)
                {
                    ShowMsg2("异常:" ex.Message socketClients.RemoteEndPoint.ToString());
                    // 从通信套接字集合中删除被中断连接的套接字对象
                    dictSocket.Remove(socketClients.RemoteEndPoint.ToString());
                    // 从通信线程集合中删除被中断连接的套接字对象
                    dictThread.Remove(socketClients.RemoteEndPoint.ToString());
                    // 从列表中移除 IP&Port
                    string online_ipandport = socketClients.RemoteEndPoint.ToString();
                    string online2_ip = online_ipandport.Substring(0, online_ipandport.LastIndexOf(":"));
                    string online3_workposition = ReadConfigFile(online2_ip);
                    lb_Online.Items.Remove(online_ipandport "|" online3_workposition);//从在线列表控件移除
                    break;//跳出循环,结束循环,线程就不执行事务了,如果少了break,在客户端关闭时,Socket.Receive方法会接收到异常数据,造成软件崩溃
                }
                catch (Exception ex)
                {
                    ShowMsg2("异常:" ex.Message);
                    break;//跳出循环,结束循环,线程就不执行事务了
                }
                // 判断第一个发送过来的数据(字节)如果是1,则代表发送过来的是文本数据
                if (arrMsgRec[0] == 0)
                {
                    string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length - 1);
                    ShowMsg(strMsgRec);
                }
                // 若是1则发送过来的是文件数据(文档,图片,视频等。。。)
                else if (arrMsgRec[0] == 1)
                {
                    // 保存文件选择框对象
                    SaveFileDialog sfd = new SaveFileDialog();
                    // 选择文件路径
                    if (sfd.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)//sfd.ShowDialog()括号中必须加入this,否则不会弹窗
                    {
                        // 获得保存文件的路径
                        string fileSavePath = sfd.FileName;
                        // 创建文件流,然后让文件流根据路径创建一个文件
                        using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
                        {
                            fs.Write(arrMsgRec, 1, length - 1);
                            
                            ShowMsg("文件保存成功:" fileSavePath);
                        }
                    }
                }
            }
        }

        //正常消息
        private void ShowMsg(string p)
        {
            string Time = Convert.ToString(DateTime.Now);
            txtMsg.SelectionColor = Color.Black;
            txtMsg.AppendText(Time " " p "\n");
            txtMsg.ScrollToCaret();//光标滚到最后一行
        }
        //异常消息
        private void ShowMsg2(string p)
        {
            string Time = Convert.ToString(DateTime.Now);
            txtMsg.SelectionColor = Color.Red;
            txtMsg.AppendText(Time " " p "\n");
            txtMsg.ScrollToCaret();//光标滚到最后一行
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(lb_Online.Text))//ListBox当前选中的文本
            {
                MessageBox.Show("请选择发送的好友!!!");
            }
            else
            {
                string strMsg = tb_Msg_Send.Text.Trim();
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                string strClientKey = lb_Online.Text.Substring(0, lb_Online.Text.IndexOf("|"));
                try
                {
                    dictSocket[strClientKey].Send(arrMsg);
                    ShowMsg("I say:" strMsg);
                }
                catch (SocketException ex)
                {
                    ShowMsg2("发送时异常:" ex.Message);
                }
                catch (Exception ex)
                {
                    ShowMsg2("发送时异常:" ex.Message);
                }
            }
        }

        /// <summary>
        /// 群发消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            string strMsg = tb_Msg_Send.Text.Trim();
            byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
            foreach (Socket item in dictSocket.Values)
            {
                item.Send(arrMsg);
            }
            ShowMsg("群发完毕!!!:)");
        }


        /// <summary>
        /// 右键关闭软件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            //foreach (KeyValuePair<string, Socket> kvp in dictSocket)
            //{
            //    try
            //    {
            //        kvp.Value.Shutdown(SocketShutdown.Both);
            //    }
            //    catch (SocketException ex)
            //    {
            //        ShowMsg2("发送时异常:" ex.Message);
            //    }
            //    catch (Exception ex)
            //    {
            //        ShowMsg2("发送时异常:" ex.Message);
            //    }
            //    kvp.Value.Close();
            //}
                Application.Exit();
        }

        /// <summary>
        /// 最小化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button6_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
        }


        /// <summary>
        /// 控制richTeztBox1的显示行数,并删除超出行数并保持剩余行颜色不变,同时始终保证滚动条和光标在最后一行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtMsg_TextChanged(object sender, EventArgs e)
        {
            if (txtMsg.Lines.Length > 100)
            {
                txtMsg.SelectionStart = 0;
                txtMsg.SelectionLength = txtMsg.GetFirstCharIndexFromLine(10);//一次选10行删掉,因为最大一次消息也不会超过10行,如果填1就只能删一行,会导致行数越来越多
                txtMsg.SelectedText = "..." "\n";//如果赋空字符串就不能正常删除超出的行,也不能保留颜色,必须给点什么
                //光标聚焦在最后一行
                txtMsg.Select(txtMsg.Text.Length, 0);
                txtMsg.ScrollToCaret();

            }
        }

        /// <summary>
        /// 单独关机
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(lb_Online.Text))//ListBox当前选中的文本
            {
                MessageBox.Show("请选择发送的好友!!!");
            }
            else
            {
                string strMsg = "关机";
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                string strClientKey = lb_Online.Text.Substring(0, lb_Online.Text.IndexOf("|"));
                try
                {
                    dictSocket[strClientKey].Send(arrMsg);
                    ShowMsg("向客户端" lb_Online.Text "发送消息:" strMsg);
                }
                catch (SocketException ex)
                {
                    ShowMsg2("发送时异常:" ex.Message);
                }
                catch (Exception ex)
                {
                    ShowMsg2("发送时异常:" ex.Message);
                }
            }
        }


        /// <summary>
        /// 全部关机
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            string strMsg = "关机";
            byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
            if (dictSocket.Count != 0)
            {
                string str = Interaction.InputBox("请输入密码", "密码", "", 680, 400);//进入设置页面前必须输入密码,使用VB里面的InputBox控件,必须引用VB.dll
                if (str == "87671678")            //如果输入密码正确,才执行单击按钮的事件响应内容,否则返回,什么都不做
                {
                    foreach (KeyValuePair<string, Socket> kvp in dictSocket)
                    {
                        try
                        {
                            kvp.Value.Send(arrMsg);
                        }
                        catch (SocketException ex)
                        {
                            ShowMsg2("发送时异常:" ex.Message);
                        }
                        catch (Exception ex)
                        {
                            ShowMsg2("发送时异常:" ex.Message);
                        }
                        ShowMsg("向客户端" kvp.Key "发送消息:" strMsg);

                    }
                    ShowMsg("群发完毕!!!:)");
                }
                else
                {
                    return;
                }
                
            }
            else
            {
                MessageBox.Show("没有连接对象!!!");
            }
        }


        /// <summary>
        /// 单独重启
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button7_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(lb_Online.Text))//ListBox当前选中的文本
            {
                MessageBox.Show("请选择发送的好友!!!");
            }
            else
            {
                string strMsg = "重启";
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                string strClientKey = lb_Online.Text.Substring(0, lb_Online.Text.IndexOf("|"));
                try
                {
                    dictSocket[strClientKey].Send(arrMsg);
                    ShowMsg("向客户端" lb_Online.Text "发送消息:" strMsg);
                }
                catch (SocketException ex)
                {
                    ShowMsg2("发送时异常:" ex.Message);
                }
                catch (Exception ex)
                {
                    ShowMsg2("发送时异常:" ex.Message);
                }
            }
        }

        /// <summary>
        ///右键显示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            this.Visible = true;
            this.WindowState = FormWindowState.Normal;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //Form1关闭时,弹窗提示,防止误关
            DialogResult TS = MessageBox.Show("确定退出?退出则客户端将全部失去连接", "警告", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (TS == DialogResult.Yes)
                e.Cancel = false;
            else
                e.Cancel = true;
        }
    }
}



网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警