C#Winform实时更新数据库信息Demo(使用Scoket)

最近在贴吧上看到有个提问就是关于怎么在Winform上实时的更新数据

提问者提到的是利用Timer去轮询,但最后经过网上查了下资料,感觉Socket也是可行的,

于是就写了这个Demo

这个Demo的思路很简单:

有一个Socket服务端,只负责接收多个客户端传过来的讯息,根据讯息内容去判断是否广播

这里每一个winform窗体程序就是一个Socket客户端,如果窗体上对数据库做了更新(例如增,删,改)操作

就会调用一个方法,该方法主要是向Socket服务端发送一个字符串"1"

当Socket服务端接收到了字符串为"1"时,则广播给所有客户端一个字符串"1"

而当客户端接收到服务端传过来一个"1"时,则立即执行数据绑定的方法(重新将界面的DataGridVeiw数据绑定)

这样就实现了一有数据改变就实时刷新的效果

下面贴出各部分代码

================服务端====================================================

服务端的界面,比较简单

public partial class Server : Form
    {
        public Server()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 已连接上的客户端集合
        /// </summary>
        List<Socket> clinetSockets;
        /// <summary>
        /// 服务端主Socket
        /// </summary>
        Socket socket;

        /// <summary>
        /// 设置数据缓冲区
        /// </summary>
        private byte[] result = new byte[1024];

        /// <summary>
        /// 开启侦听按钮点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            //初始化
            clinetSockets = new List<Socket>();
            //创建socket对象
             socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //获取ip地址和端口(其实应该把它放在配置文件中,客户端的ip和port都放在配置文件中)
            IPAddress ip = IPAddress.Parse(txtIPAddress.Text.Trim());
            int port = Convert.ToInt32(txtPort.Text.Trim());
            IPEndPoint point = new IPEndPoint(ip, port);

            //绑定ip和端口
            socket.Bind(point);
            //设置最大连接数
            socket.Listen(10);

            listBox1.Items.Add("服务器已开启,等待客户端连接中.....");

            //开启新线程监听
            Thread serverThread = new Thread(ListenClientConnect);
            serverThread.IsBackground = true;
            serverThread.Start(socket);

        }

        /// <summary>
        /// 监听传入
        /// </summary>
        /// <param name="ar"></param>
        private void ListenClientConnect(object ar)
        {
            //设置标志
            bool flag = true;
            //获得服务器的Socket
            Socket serverSocket = ar as Socket;
            //轮询
            while (flag)
            {
                //获得连入的客户端socket
                Socket clientSocket = serverSocket.Accept();
                //将新加入的客户端加入列表中
                clinetSockets.Add(clientSocket);

                //向listbox中写入消息
                listBox1.Invoke(new Action(() => {
                    listBox1.Items.Add(string.Format("客户端{0}已成功连接到服务器\r\n", clientSocket.RemoteEndPoint));
                }));
                //开启新的线程,进行监听客户端消息
                var mReveiveThread = new Thread(ReceiveClient);
                mReveiveThread.IsBackground = true;
                mReveiveThread.Start(clientSocket);
            }

        }

        /// <summary>
        /// 接收客户端传过来的数据
        /// </summary>
        /// <param name="obj"></param>
        private void ReceiveClient(object obj)
        {
            //获取当前客户端
            //因为每次发送消息的可能并不是同一个客户端,所以需要使用var来实例化一个新的对象
            //可是我感觉这里用局部变量更好一点
            var mClientSocket = (Socket)obj;
            // 循环标志位
            bool flag = true;
            while (flag)
            {
                try
                {
                    //获取数据长度
                    int receiveLength = mClientSocket.Receive(result);
                    //获取客户端消息
                    string clientMessage = Encoding.UTF8.GetString(result, 0, receiveLength);
                    //服务端负责将客户端的消息分发给各个客户端
                    //判断客户端发来的消息是否是预定的标志
                    if (clientMessage=="1")
                    {
                        //通知各客户端
                        this.SendMessage("1");
                    }

                    //向listbox中写入消息
                    listBox1.Invoke(new Action(() => {
                        listBox1.Items.Add(string.Format("客户端{0}发来消息{1}", mClientSocket.RemoteEndPoint, clientMessage));
                    }));

                }
                catch(Exception e)
                {
                    //从客户端列表中移除该客户端
                    clinetSockets.Remove(mClientSocket);

                    //显示客户端下线消息
                    listBox1.Invoke(new Action(() =>
                    {
                        listBox1.Items.Add(string.Format("服务器发来消息:客户端{0}从服务器断开,断开原因:{1}\r\n", mClientSocket.RemoteEndPoint, e.Message));
                    }));

                    //断开连接
                    mClientSocket.Shutdown(SocketShutdown.Both);
                    mClientSocket.Close();
                    break;
                }
            }
        }

        /// <summary>
        /// 向所有的客户端群发消息
        /// </summary>
        /// <param name="msg">message</param>
        public void SendMessage(string msg)
        {
            //确保消息非空以及客户端列表非空
            if (msg == string.Empty || clinetSockets.Count <= 0) return;
            //向每一个客户端发送消息
            foreach (Socket s in this.clinetSockets)
            {
                (s as Socket).Send(Encoding.UTF8.GetBytes(msg));
            }
        }

        /// <summary>
        /// 窗体关闭后释放资源
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Server_FormClosing(object sender, FormClosingEventArgs e)
        {

        }
    }

======================================客户端=================================

public partial class Clinet : Form
    {
        public Clinet()
        {
            InitializeComponent();
        }

        //创建数据对象
        Data get = new 客户端.Data();

        /// <summary>
        /// 客户端的Socket
        /// </summary>
        Socket clinet;

        private void Clinet_Load(object sender, EventArgs e)
        {
            RefTable();
            //创建socket
            CreateSocket();
        }

        /// <summary>
        /// 创建客户端的Socket
        /// </summary>
        private void CreateSocket()
        {
            // 创建socket
            clinet = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //连接
            //获得ip和端口(读取配置文件)
            var app = System.Configuration.ConfigurationManager.AppSettings;
            IPEndPoint point = new IPEndPoint(IPAddress.Parse(app["ip"]), Convert.ToInt32(app["port"]));

            //连接服务器
            clinet.Connect(point);

            //开启新线程获取服务器端消息
            Thread thClinet = new Thread(new ThreadStart(CallRec));
            thClinet.IsBackground = true;
            thClinet.Start();
        }

        /// <summary>
        /// 接收消息
        /// </summary>
        private void CallRec()
        {
            bool flag = true;
            while (flag)
            {
                byte[] recBuf = new byte[1024];
                //获取返回数据的长度
                int length = clinet.Receive(recBuf);
                //获取监听到的数据
                string reslut = Encoding.UTF8.GetString(recBuf, 0, length);

                if (reslut == "1")
                {
                    //刷新表格数据
                    RefTable();
                }
            }
        }

        /// <summary>
        /// 刷新表格
        /// </summary>
        private void RefTable()
        {
            dataGridView1.Invoke(new Action(() =>
            {
                dataGridView1.DataSource = get.GetPersonList();
            }));

        }

        /// <summary>
        /// 添加数据事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAdd_Click(object sender, EventArgs e)
        {
            //获取用户输入
            string name = txtAddName.Text;
            int age = Convert.ToInt32(txtAgeAdd.Text);
            string phone = txtPhoneAdd.Text;

            //实例化一个数据对象
            Person p = new Person() { Name = name, Age = age, Phone = phone };
            //写入数据
            AddList(p);
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="p"></param>
        private void AddList(Person p)
        {
            //获取数据集合
            List<Person> list = dataGridView1.DataSource as List<Person>;
            //加入数据
            list.Add(p);
            //加入数据
            bool b = get.Add(list);
            if (b)
            {
                MessageBox.Show("增加成功");
                //增加成功后发送socket信息
                //向服务器发送消息
                clinet.Send(Encoding.UTF8.GetBytes("1"));
            }
            else
            {
                MessageBox.Show("增加失败");
            }
        }

        private void Clinet_FormClosing(object sender, FormClosingEventArgs e)
        {

        }
    }

客户端是读取的本地Json数据创建的对象集合用以模拟数据库

class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Phone { get; set; }
    }
 class Data
    {
        System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer();
        public List<Person> GetPersonList()
        {
            //读取json数据
            string jsonStr = File.ReadAllText("Data.json");

            List<Person> list = js.Deserialize<List<Person>>(jsonStr);
            return list;
        }

        public bool Add(List<Person> list)
        {
            //向数据中覆盖追加
            string strJson = js.Serialize(list);
            try
            {
                File.WriteAllText("Data.json", strJson);
                return true;
            }
            catch
            {

                return false;
            }

        }
    }

Data.json数据

[
  {
    "name": "张三",
    "age": 14,
    "phone": "13888888888"
  },
  {
    "name": "张三",
    "age": 14,
    "phone": "13888888888"
  },
  {
    "name": "张三",
    "age": 14,
    "phone": "13888888888"
  },
  {
    "name": "张三",
    "age": 14,
    "phone": "13888888888"
  },
  {
    "name": "张三",
    "age": 14,
    "phone": "13888888888"
  },
  {
    "name": "张三",
    "age": 14,
    "phone": "13888888888"
  },
  {
    "name": "张三",
    "age": 14,
    "phone": "13888888888"
  }
]

====================================运行效果图==============================

=========================================分割线==================================

其实个人觉得可以把服务端做成一个Windows服务更好

代码打包地址(内含windows服务代码)

关于如何将windows服务如何安装到服务中,网上教程很多,请自行百度

https://pan.baidu.com/s/1J6SIGxwzzvG-B1ACyDWPKw

个人拙作,敬请谅解.

原文地址:https://www.cnblogs.com/rbzz/p/9152941.html

时间: 2024-10-16 16:20:39

C#Winform实时更新数据库信息Demo(使用Scoket)的相关文章

第十二章——SQLServer统计信息(1)——创建和更新统计信息

原文:第十二章--SQLServer统计信息(1)--创建和更新统计信息 简介: 查询的统计信息: 目前为止,已经介绍了选择索引.维护索引.如果有合适的索引并实时更新统计信息,那么优化器会选择有用的索引供查询之用,因为SQLServer优化器是基于开销的优化.当在where和on上的列上的数据需要显示在结果集的时候,如果有实时的统计信息,优化器会选择最好的执行方式,因为优化器会从统计信息中获得这些数据的明细情况. 在创建索引的时候,SQLServer就会在索引列上创建统计信息.简单来说,统计信息

在 Android Studio 上实时调试数据库( SQLite )

安装 SQLScout 是一个 Android Studio 的插件,通过点击: Setting -> Plugings -> Browse Repositories 1 搜索 SQLScout 安装即可. 要是下载不动,可以到 这里 下载,然后点击 Install plugin from disk 导入. 加载 成功安装后重启 Android Studio,会发现右边的侧边栏出现了 SQLite Exporer,展开后点击「+」会出现三个选项:  Local SQLite Database

JDBC连接数据库(MySql)步骤,以及查询、插入、删除、更新等十一个处理数据库信息的功能。

主要内容:  JDBC连接数据库步骤. 一个简单详细的查询数据的例子. 封装连接数据库,释放数据库连接方法. 实现查询,插入,删除,更新等十一个处理数据库信息的功能. 把十一个功能都放在一起. 一.JDBC连接数据库(编辑)步骤(主要有六个步骤).  1.注册驱动: Class.formName("com.mysql.jdbc.Driver");  2.获取连接:(1) param1:  要连接数据库的url-----> String url="jdbc:mysql:/

JDBC连接(MySql)数据库步骤,以及查询、插入、删除、更新等十一个处理数据库信息的功能

主要内容:  JDBC连接数据库步骤. 一个简单详细的查询数据的例子. 封装连接数据库,释放数据库连接方法. 实现查询,插入,删除,更新等十一个处理数据库信息的功能.(包括事务处理,批量更新等) 把十一个功能都放在一起. 安装下载的数据库驱动程序jar包,不同的数据库需要不同的驱动程序(这本该是第一步,但是由于属于安装类,所以我们放在最后) 一.JDBC连接数据库(编辑)步骤(主要有六个步骤).  1.注册驱动: Class.forName("com.mysql.jdbc.Driver"

使用hibernate更新数据库记录的信息的相关学习记录

截选代码(可能遗漏标点符号): package name.sql; import java.util.List; import name.session.HibernateSessionFactory; import org.hibernate.Query;import org.hibernate.Session;import org.hibernate.Transaction; public class SqlHelper { //增 public void save(Object obj){

SharePoint 2013 数据库中手动更新用户信息

在SharePoint的使用过程中,尤其是Windows认证的情况下,而且没有配置用户配置文件服务,经常会出现如果更新AD中的用户信息(包括名字.显示名.邮件等),SharePoint这边站点并不会更新的情况. 这时候,我们经常会操作数据进行更新操作,生产环境建议备份,测试环境也要多看几次update语句. 1.首先进入授权的用户组,看到我们的用户名,当AD中更新,这里的Name还是之前的名字,如下: 2.鼠标放到名字上,可以看到Url链接地址,这时候我们需要ListId和ID,ListId是用

数据库参数调优--自动更新统计信息

数据库参数调优--自动更新统计信息 原文: https://blog.csdn.net/z10843087/article/details/78356975 背景 我们都知道SQL SERVER 借助统计信息来产生执行计划,而过时的统计信息会导致SQL SERVER选择错误的执行计划,导致严重的性能问题.  在数据库中选项可以自动的更新统计信息.如下图: 默认他是开启的,所以我们很少去关注他或者修改他. 异步更新和同步更新 其实除了同步更新统计信息外,还有一个异步更新统计信息的选项.他和同步更新

EntityFramework Code First Demo 更新数据库

1.使用Nuget安装EntityFramework 2.AppConfig文件 <?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?Li

基于server broker 的数据实时更新

Service Broker介绍:SQL Server Service Broker 为消息和队列应用程序提供 SQL Server 数据库引擎本机支持.这使开发人员可以轻松地创建使用数据库引擎组件在完全不同的数据库之间进行通信的复杂应用程序.开发人员可以使用 Service Broker 轻松生成可靠的分布式应用程序.使用 Service Broker 的应用程序开发人员无需编写复杂的内部通信和消息,即可跨多个数据库分发数据工作负荷.因为 Service Broker 会处理会话上下文中的通信