最近因为业务的需求,需要实现串口的透传(简单的TCP/UDP透传),并且显示TCP/UDP实时刷新和显示连接情况或者监听情况。非常简单的功能,
但是会存在一些雷点
,我会讲述成功实现的做法还有我踩过的坑。
效果如下两张图。
1.使用Sql Server 创建一个数据库并且分离,并且放入程序目录下,并且连接路径改为目录下。
2.建立Linq to sql类。
3.创建串口时,将数据全部插入数据库。(连接状态文字栏根据选用的网络协议进行改变)
4.插入完成后,将数据填充显示。
5.TCP/UDP监听状态下,有客户端连入,则改变连接状态,断开也更新状态。
1,2,3,4步想必大家都会,就不再赘述,关键是第5步。 我们需要在监听部分进行捕捉到客户端的连接,并且及时更新数据库。
首先,我们要获取到数据库的那一条要更新的记录才能做更新操作。作为服务端,其端口是唯一的,所以我们获取到它的端口:
((IPEndPoint)serverSocket.LocalEndPoint).Port.ToString();
serverSocket
:是服务端用来监听的载体。
LocalEndPoint
:可以获取当前服务器的各种信息。但是不可读取。
(IPEndPoint)
:强制转换成IPEndPoint类型,就调用Port方法,拿到了
LocalEndPoint
中我们实际使用的端口号了。
之后写一个方法,用拿到的端口号去数据库中查询,并且更新:
private void ReturnendPoint(Socket socket)//根据端口号返回数据库中的对象
vspdTableDataContext db = new vspdTableDataContext();//实例化
var res = (from r in db.PortSettingTable
where r.localportnum == ((IPEndPoint)socket.LocalEndPoint).Port.ToString().Trim()//查找端口号是否一致
select r).FirstOrDefault();
res.connetstate = "已经连接";
db.SubmitChanges();
但是这样的话,还达不到要求,因为只是改成了 “已经连接”,但是没有具体显示连接人数。 所以我们这里新建一个全局变量来存储每个端口号对应的人数,我这里用了字典:
Dictionary<string,int>OnlineNums=new Dictionary<string,int>();
在服务端开启监听的时候,我们就加入客户端的端口号和在线人数(刚刚开始监听,肯定是0): OnlineNums.Add(PortTxt, 0);
然后再改写一下我们上面的方法,我们希望把每个端口对应的在线人数同时传输进去进行更新,像这样:
ReturnendPoint(serverSocket, OnlineNums[port]);
而具体方法就是如下:
private void ReturnendPoint(Socket socket,int index)//根据端口号返回数据库中的对象
vspdTableDataContext db = new vspdTableDataContext();//实例化
var res = (from r in db.PortSettingTable
where r.localportnum == ((IPEndPoint)socket.LocalEndPoint).Port.ToString().Trim()//查找端口号是否一致
select r).FirstOrDefault();
if(index>0)
res.connetstate = $"已经连接({index})";
else//如果小于或等于0证明没人了
res.connetstate = "正在监听";
db.SubmitChanges();
然后我们在监听方法里边调用:
public void AcceptClientConnet(object socket)//接收客户端连接的方法
var serverSocket = socket as Socket;//强制转换
string port = ((IPEndPoint)serverSocket.LocalEndPoint).Port.ToString();//获得端口号
while (true)
var ProxSocket = serverSocket.Accept();//用户连接
OnlineNums[port]++;//人数+1
ReturnendPoint(serverSocket, pairs[port]);//更新数据库
DataBind();//重新填充,刷新datagirdview
ThreadPool.QueueUserWorkItem(ReceiveData, ProxSocket);//为了反复连接,使用线程池
在客户端断线的时候也是如法炮制:
public void ReceiveData(object socket)//接收客户端消息的方法
var ProxSocket = socket as Socket;
byte[] data = new byte[1024 * 1024];//接收消息的缓冲区
string port = ((IPEndPoint)ProxSocket.LocalEndPoint).Port.ToString();
while (true)
int len = 0;//记录消息长度
len = ProxSocket.Receive(data, 0, data.Length, SocketFlags.None);
catch (Exception)
//异常退出
OnlineNums[port]--;//人数-1
ReturnendPoint(ProxSocket, OnlineNums[port]);//重新填充,刷新datagirdview
DataBind();
return;
if (len <= 0)
//如果小于0,证明无连接,服务端正常退出
OnlineNums[port]--;//人数-1
ReturnendPoint(ProxSocket, OnlineNums[port]);//重新填充,刷新datagirdview
DataBind();
ps.StopConnet(ProxSocket);
return;//让方法结束,终结当前接收服务端数据的异步线程
这样的写法有点累赘,可以写成下面的形式:
ReturnendPoint(ProxSocket, OnlineNums[++port]);
ReturnendPoint(ProxSocket, OnlineNums[--port]);
这样就已经实现效果了。
- 如果用了Linq to Sql去填充DataGridView,就不要试图去直接改写单元格中的Value,这样没用。虽然会能赋值到目标单元格上的Value上,但是不会显示出来。因为数据会被你原本的DataSource覆盖。
- Linq to Sql的DataContext不要做全局变量的实例化。如果你填充数据集的方法和更新数据集的方法是在一个类里面的话,共用一个实例会出各种各样的错误。应该在独立方法体内实例化。但如果两个方法不在一个类中,随便。(天呐,简直是弱智级别的错误啊啊啊啊啊)
- 记得给DataGridView做跨线程处理。
using MySql.Data.MySqlClient;using System; using System.Data; using System.Threading; using System.Windows.Forms;
namespace DataGirdView{ public partial class Form1 : Form { Thread ...
本文讨论的主要问题是C#连接MySQL数据库实现 select 多结果集返回,并将结果用DataGridView定时更新。
一、实现中遇到的问题
1、刷新DataGridView显示时出错或者出现大红叉。
2、未将对象引用设置添加到对象的实例。
出现上述问题的可能原因:
1、未能正确使用委托。
2、由于select查询语句过多,导致连接关闭数据库次数频繁。
主要难点:
1、Mysql返回多结果集java和Php的较多,C#的完整代码较少。
2、MySQL中定义的表表之间的关联性比较弱,表间只有sensorI
本文主要讲诉在使用VS2012+SQL Server数据库做系统中,通常会遇到几个问题.使用dataGridView控件在修改、删除、插入数据后,怎样刷新数据显示操作后的结果.同时在对数据操作时通常会判断数据的主键是否存在或重复,判断外键是否重复,这几个问题我推荐使用函数的形式完成,同时推荐一个操作格式,下面将详细介绍.
一.dataGridView刷新数据
如下图所示,在数据库中删除一个数据...
针对DataGridView中已进行过数据绑定,即已向DataGridView中添加了一些数据,可以结合Linq查询,并让匹配查询的行高亮显示,如下图:
具体实现如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
na...
有一种情况,datagridview不是通过绑定datatable刷新数据的,可以采用
this.datagridview.refreshedit来刷新修改的数据,例如:
//做数据验证,格式化成两位小数,更新不了数据,
private void skinDataGridView1_CellValidating(object sender, DataGridViewCellValidatingEv...
LINQ to SQL is a technology that enables developers to use LINQ (Language Integrated Query) to access data stored in Microsoft SQL Server databases. With LINQ to SQL, developers can write queries using C# or VB.NET instead of SQL, which provides a more intuitive and type-safe way to work with data.
LINQ to SQL provides a mapping between the database schema and the classes in the application, allowing developers to work with data as objects rather than as rows in a table. This makes it easier to write and maintain code, as well as improving performance by reducing the number of database calls needed to retrieve or update data.
LINQ to SQL also supports features like change tracking, which allows developers to detect and handle changes to data made by other users or applications. It also provides support for transactions, allowing developers to ensure that multiple database operations are atomic and consistent.
Overall, LINQ to SQL is a powerful tool for developers working with Microsoft SQL Server databases, offering a more productive and efficient way to access and manipulate data.