C#基于MVC模式实现TCP三次握手,附带简易日志管理模块

news2025/3/31 2:49:50

C#基于MVC模式实现TCP三次握手

  • 1 Model
    • 1.1 ServerModel
    • 1.2 ClientModel
    • 1.3 配置参数模块
    • 1.4 日志管理模块
      • 1.4.1 数据结构
      • 1.4.1 日志管理工具类
      • 1.4.1 日志视图展示
        • 1.4.1.1 UcLogManage.cs
        • 1.4.1.2 UcLogManage.Designer.cs
  • 2 视图(View)
    • 2.1 ViewServer
      • 2.1.1 ViewServer.cs
      • 2.1.1 ViewServer.Designer.cs
    • 2.2 ViewClient
      • 2.2.1 ViewClient.cs
      • 2.2.1 ViewClient.Designer.cs
  • 3 控制器(Controller)
    • 3.1 ServerController
    • 3.2 ClientController
  • 4 工具类

友情资料链接: TCP三次握手

1 Model

1.1 ServerModel

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DemoThreeTimesHandshake.Model
{
    public class ServerModel
    {
        private TcpListener _server;
        private bool _isRunning;

        public Action<TcpClient, Config.MyEnum, string> EventAddLog;

        ~ServerModel()
        {
            CloseServer();
        }

        public void OpenServer()
        {
            //创建一个 TCP 监听器,监听本地 IP 地址和端口
            _server = new TcpListener(IPAddress.Any, Config.Server.Port);
            // 启动服务器
            _server.Start();

            _isRunning = true;
            new Task(() =>
            {
                while (_isRunning)
                {
                    Thread.Sleep(1000);
                    ListeningClient();
                }

            }).Start();
        }

        public void CloseServer()
        {
            if (_isRunning)
            {
                // 停止服务器
                _server.Stop();
            }
        }

        /// <summary>
        /// 监听接入客户端,三次握手
        /// </summary>
        private void ListeningClient()
        {
            TcpClient client = null;
            try
            {
                //等待客户端连接
                client = _server.AcceptTcpClient();
                AddLog(client, Config.MyEnum.State, "已连接");

                //获取网络流
                NetworkStream stream = client.GetStream();

                //第一次握手:接收客户端的 SYN 包
                byte[] buffer = new byte[1024];
                int bytesRead = stream.Read(buffer, 0, buffer.Length);
                string synMessage = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                AddLog(client, Config.MyEnum.Receive, synMessage);

                //第二次握手:发送 SYN+ACK 包
                string synAckMessage = "SYN+ACK";
                byte[] synAckBuffer = Encoding.ASCII.GetBytes(synAckMessage);
                stream.Write(synAckBuffer, 0, synAckBuffer.Length);
                AddLog(client, Config.MyEnum.Send, synAckMessage);

                //第三次握手:接收客户端的 ACK 包
                bytesRead = stream.Read(buffer, 0, buffer.Length);
                string ackMessage = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                AddLog(client, Config.MyEnum.Receive, ackMessage);
                AddLog(client, Config.MyEnum.State, "三次握手完成,连接建立成功。");

                //为(每个)客户端创建线程处理通信
                new Task(() => HandleClient(client)).Start();
            }
            catch (Exception ex)
            {
                AddLog(client, Config.MyEnum.State, $"发生错误: {ex.Message}");
            }
        }

        private void HandleClient(TcpClient client)
        {
            try
            {
                NetworkStream stream = client.GetStream();
                byte[] buffer = new byte[1024];

                while (_isRunning)
                {
                    // 异步读取客户端发送的消息
                    int bytesRead = stream.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0)
                    {
                        // 客户端断开连接
                        break;
                    }

                    string message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                    AddLog(client, Config.MyEnum.Receive, message);

                    // 将接收到消息回发给客户端
                    string synMessage = message;
                    byte[] synBuffer = System.Text.Encoding.ASCII.GetBytes(synMessage);
                    stream.Write(synBuffer, 0, synBuffer.Length);
                    AddLog(client, Config.MyEnum.Send, synMessage);
                }
            }
            catch (Exception ex)
            {
                AddLog(client, Config.MyEnum.State, ex.Message);
            }
        }

        private void AddLog(TcpClient client, Config.MyEnum type, string description)
        {
            EventAddLog?.Invoke(client, type, description);
        }

    }
}

1.2 ClientModel

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace DemoThreeTimesHandshake.Model
{
    public class ClientModel
    {
        public Action<TcpClient, Config.MyEnum, string> EventAddLog;

        private TcpClient _client;
        private bool _isRunning;

        ~ClientModel()
        {
            CloseServer();
        }

        public void OpenServer()
        {
            StartClient();
        }

        public void CloseServer()
        {
            if (_isRunning)
            {
                _client.Close();
            }
        }

        private void StartClient()
        {
            try
            {
                // 创建一个 TCP 客户端,连接到服务器的 IP 地址和端口 8888
                _client = new TcpClient();
                _client.Connect(IPAddress.Parse(Config.Server.IP), Config.Server.Port);
                AddMsg(Config.MyEnum.State, "已连接到服务器。");
                _isRunning = true;

                // 获取网络流
                NetworkStream stream = _client.GetStream();

                // 第一次握手:发送 SYN 包
                string synMessage = "SYN";
                byte[] synBuffer = System.Text.Encoding.ASCII.GetBytes(synMessage);
                stream.Write(synBuffer, 0, synBuffer.Length);
                AddMsg(Config.MyEnum.Send, $"发送 SYN 包: {synMessage}");

                // 第二次握手:接收服务器的 SYN+ACK 包
                byte[] buffer = new byte[1024];
                int bytesRead = stream.Read(buffer, 0, buffer.Length);
                string synAckMessage = System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead);
                AddMsg(Config.MyEnum.Receive, $"收到服务器的 SYN+ACK 包: {synAckMessage}");

                // 第三次握手:发送 ACK 包
                string ackMessage = "ACK";
                byte[] ackBuffer = System.Text.Encoding.ASCII.GetBytes(ackMessage);
                stream.Write(ackBuffer, 0, ackBuffer.Length);
                AddMsg(Config.MyEnum.Send, $"发送 ACK 包: {ackMessage}");
                AddMsg(Config.MyEnum.State, "三次握手完成,连接建立成功。");

                // 客户端创建一个新的线程来处理通信
                new Task(HandleClient).Start();
            }
            catch (Exception ex)
            {
                AddMsg(Config.MyEnum.State, $"异常: {ex.Message}");
            }
        }

        private void HandleClient()
        {
            try
            {
                NetworkStream stream = _client.GetStream();
                byte[] buffer = new byte[1024];

                while (_isRunning)
                {
                    // 异步读取客户端发送的消息
                    int bytesRead = stream.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0) break;

                    string message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                    AddMsg(Config.MyEnum.Receive, message);
                }
            }
            catch (Exception ex)
            {
                AddMsg(Config.MyEnum.State, $"异常: {ex.Message}");
            }
        }

        private void AddMsg(Config.MyEnum type, string message)
        {
            EventAddLog?.Invoke(_client, type, message);
        }

        public void Send(string textAsc)
        {
            if (_client == null) return;
            // 获取网络流
            NetworkStream stream = _client.GetStream();
            byte[] synBuffer = Encoding.ASCII.GetBytes(textAsc);
            stream.Write(synBuffer, 0, synBuffer.Length);
            AddMsg(Config.MyEnum.Send, $"发送包长度: {synBuffer.Length}");
        }

        public void GetClientInfo(out string ip, out int port)
        {
            try
            {
                IPEndPoint clientEndPoint = (IPEndPoint)_client.Client.RemoteEndPoint;
                ip = clientEndPoint.Address.ToString();
                port = clientEndPoint.Port;
            }
            catch (Exception ex)
            {
                ip = "";
                port = 0;
            }
        }

    }
}

1.3 配置参数模块

using System;
using System.ComponentModel;


namespace DemoThreeTimesHandshake.Model
{
    public class Config
    {

        public class Server
        {

            public const string IP = "127.0.0.1";

            public const int Port = 1234;

        }


        [Serializable]
        public enum MyEnum
        {

            [Description("状态信息")]
            State,

            [Description("发送")]
            Send,

            [Description("接受")]
            Receive

        }

    }
}

1.4 日志管理模块

1.4.1 数据结构

using System;
using System.ComponentModel;

namespace DemoThreeTimesHandshake.Model.LogDS
{
    [Serializable]
    public class Log
    {
        [Description("时间")]
        public string Time { get; set; }

        [Description("IP")]
        public string IP { get; set; }

        [Description("类型")]
        public Config.MyEnum Type { get; set; }

        [Description("端口")]
        public int Port { get; set; }

        [Description("内容")]
        public string Description { get; set; }

        public Log(string time, string ip, int port, Config.MyEnum type, string description)
        {
            Time = time;
            IP = ip;
            Port = port;
            Type = type;
            Description = description;
        }
    }
}

1.4.1 日志管理工具类

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows.Forms;
using DemoThreeTimesHandshake.Tool;

namespace DemoThreeTimesHandshake.Model.LogDS
{
    public class LogUtil
    {
        public enum ELog { First, Previous, Next, Last, Clear, Save }

        /// <summary>
        /// 记录日志信息
        /// </summary>
        private List<Log> _list = new List<Log>();

        /// <summary>
        /// 当前页索引
        /// </summary>
        private int _curPageIndex;

        private int _pageCount = 12;

        /// <summary>
        /// 日志元素数
        /// </summary>
        public int LogCount => _list.Count;

        /// <summary>
        /// 每页展示的数据量
        /// </summary>
        public int PageCount
        {
            get => _pageCount;
            set
            {
                _curPageIndex = 0;
                _pageCount = value;
            }
        }

        /// <summary>
        /// 总页数
        /// </summary>
        private int PageSum
        {
            get
            {
                int count = LogCount / PageCount;
                if (LogCount % PageCount > 0) count += 1;
                return count;
            }
        }

        /// <summary>
        /// 获取当前页(List)
        /// </summary>
        public List<Log> GetCurPage
        {
            get
            {
                var list = new List<Log>();
                for (int i = 0, index = _curPageIndex * PageCount; i < PageCount && index >= 0 && index < LogCount; i++, index++)
                {
                    list.Add(_list[index].DeepCopy());
                }
                return list;
            }
        }

        /// <summary>
        /// 获取当前页(DataTable)
        /// </summary>
        public DataTable GetCurPageTable
        {
            get
            {
                DataTable table = new DataTable();
                table.Columns.Add("序号");
                table.Columns.Add(nameof(Log.Time));
                table.Columns.Add(nameof(Log.IP));
                table.Columns.Add(nameof(Log.Type));
                table.Columns.Add(nameof(Log.Port));
                table.Columns.Add(nameof(Log.Description));
                for (int i = 0, index = _curPageIndex * PageCount; i < PageCount && index >= 0 && index < LogCount; i++, index++)
                {
                    var t = _list[index];
                    table.Rows.Add(index + 1, t.Time, t.IP, t.Type, t.Port, t.Description);
                }
                return table;
            }
        }

        /// <summary>
        /// 当前页页码信息
        /// </summary>
        public string PageInfo => $"第{_curPageIndex + 1}页,共{PageSum}页";

        /// <summary>
        /// 添加日志
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <param name="type"></param>
        /// <param name="description"></param>
        public void AddLog(string ip, int port, Config.MyEnum type, string description)
        {
            var time = DateTime.Now.ToString("F");
            _list.Add(new Log(time, ip, port, type, description));
            _curPageIndex = PageSum - 1;
        }

        public void LogManage(ELog type)
        {
            switch (type)
            {
                case ELog.First:
                    _curPageIndex = 0;
                    break;
                case ELog.Previous:
                    if (PageSum > 0)
                    {
                        _curPageIndex -= 1;
                        if (_curPageIndex < 0) _curPageIndex = PageSum - 1;
                    }
                    break;
                case ELog.Next:
                    if (PageSum > 0) _curPageIndex = (_curPageIndex + 1) % PageSum;
                    break;
                case ELog.Last:
                    _curPageIndex = PageSum - 1;
                    break;
                case ELog.Clear:
                    _list.Clear();
                    _curPageIndex = 0;
                    break;
                case ELog.Save:
                    SaveLog();
                    break;
            }
            if (PageSum <= 0) _curPageIndex = 0;
        }

        public void SaveLog()
        {
            try
            {
                SaveFileDialog dialog = new SaveFileDialog();
                dialog.FileName = $"日志_{DateTime.Now:F}";
                dialog.Filter = "|*.csv";
                if (dialog.ShowDialog() != DialogResult.OK) return;
                string split = ",";
                StringBuilder builder = new StringBuilder();
                builder.Append("序号" + split);
                builder.Append(nameof(Log.Time) + split);
                builder.Append(nameof(Log.IP) + split);
                builder.Append(nameof(Log.Type) + split);
                builder.Append(nameof(Log.Port) + split);
                builder.Append(nameof(Log.Description));
                builder.AppendLine();
                int num = 1;
                foreach (var log in _list)
                {
                    builder.Append(num++ + split);
                    builder.Append(log.Time + split);
                    builder.Append(log.IP + split);
                    builder.Append(log.Type + split);
                    builder.Append(log.Port + split);
                    builder.Append(log.Description);
                    builder.AppendLine();
                }
                File.WriteAllText(dialog.FileName, builder.ToString());
                Process.Start(dialog.FileName);
            }
            catch (Exception ex)
            {
                MessageBox.Show("保存日志文件失败:" + ex.Message);
            }
        }
    }
}

1.4.1 日志视图展示

在这里插入图片描述

1.4.1.1 UcLogManage.cs
using System;
using System.Linq;
using System.Windows.Forms;
using DemoThreeTimesHandshake.Tool;

namespace DemoThreeTimesHandshake.Model.LogDS
{
    public partial class UcLogManage : UserControl
    {
        private LogUtil _logUtil;
        private string[] _hideColumnName;

        public UcLogManage(LogUtil logUtil, params string[] hideColumnName)
        {
            InitializeComponent();
            _hideColumnName = hideColumnName;
            _logUtil = logUtil;
            menu_FirstPage.Click += (o, args) => ClickManage(LogUtil.ELog.First);
            menu_PreviousPage.Click += (o, args) => ClickManage(LogUtil.ELog.Previous);
            menu_NextPage.Click += (o, args) => ClickManage(LogUtil.ELog.Next);
            menu_LastPage.Click += (o, args) => ClickManage(LogUtil.ELog.Last);
            menu_ClearLog.Click += (o, args) => ClickManage(LogUtil.ELog.Clear);
            menu_SaveLog.Click += (o, args) => ClickManage(LogUtil.ELog.Save);
            com_PageCount.Text = logUtil.PageCount.ToString();
            com_PageCount.TextChanged += (o, args) =>
            {
                if (!int.TryParse(com_PageCount.Text, out var count)) return;
                _logUtil.PageCount = count;
                RefreshDataGridView();
            };
            menu_PageInfo.Text = string.Empty;
        }

        private void ClickManage(LogUtil.ELog type)
        {
            _logUtil.LogManage(type);
            RefreshDataGridView();
        }


        private void RefreshDataGridView()
        {
            if (InvokeRequired)
            {
                Invoke(new EventHandler(delegate { RefreshDataGridView(); }));
                return;
            }

            menu_PageInfo.Text = _logUtil.PageInfo;
            if (true)
            {
                dataGridView1.DataSource = _logUtil.GetCurPageTable;
            }
            else
            {
                dataGridView1.DataSource = _logUtil.GetCurPage.ToList();
            }

            dataGridView1.Columns["序号"].FillWeight = 1;
            SetDataGridViewStyle(nameof(Log.Time), 2);
            SetDataGridViewStyle(nameof(Log.IP), 1);
            SetDataGridViewStyle(nameof(Log.Port), 1);
            SetDataGridViewStyle(nameof(Log.Type), 1);
            SetDataGridViewStyle(nameof(Log.Description), 5);
            for (int i = 0; i < _hideColumnName.Length; i++)
            {
                dataGridView1.Columns[_hideColumnName[i]].Visible = false;
            }
            Utility.SetDgvStyle(dataGridView1);
        }

        private void SetDataGridViewStyle(string propertyName, int fillWeight)
        {
            string headerText = Utility.GetPropertyDescription<Log>(propertyName);
            dataGridView1.Columns[propertyName].HeaderText = headerText;
            dataGridView1.Columns[propertyName].FillWeight = fillWeight;
        }

        public void DisplayResult()
        {
            RefreshDataGridView();
        }
    }
}

1.4.1.2 UcLogManage.Designer.cs
namespace DemoThreeTimesHandshake.Model.LogDS
{
    partial class UcLogManage
    {
        /// <summary> 
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary> 
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region 组件设计器生成的代码

        /// <summary> 
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.menuStrip1 = new System.Windows.Forms.MenuStrip();
            this.menu_FirstPage = new System.Windows.Forms.ToolStripMenuItem();
            this.menu_PreviousPage = new System.Windows.Forms.ToolStripMenuItem();
            this.menu_NextPage = new System.Windows.Forms.ToolStripMenuItem();
            this.menu_LastPage = new System.Windows.Forms.ToolStripMenuItem();
            this.menu_ClearLog = new System.Windows.Forms.ToolStripMenuItem();
            this.menu_PageInfo = new System.Windows.Forms.ToolStripMenuItem();
            this.menu_LogManage = new System.Windows.Forms.ToolStripMenuItem();
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.menu_SaveLog = new System.Windows.Forms.ToolStripMenuItem();
            this.每页显示日志条数ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.com_PageCount = new System.Windows.Forms.ToolStripComboBox();
            this.menuStrip1.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            this.SuspendLayout();
            // 
            // menuStrip1
            // 
            this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.menu_LogManage,
            this.menu_FirstPage,
            this.menu_PreviousPage,
            this.menu_NextPage,
            this.menu_LastPage,
            this.menu_ClearLog,
            this.menu_PageInfo});
            this.menuStrip1.Location = new System.Drawing.Point(0, 0);
            this.menuStrip1.Name = "menuStrip1";
            this.menuStrip1.Size = new System.Drawing.Size(703, 25);
            this.menuStrip1.TabIndex = 9;
            this.menuStrip1.Text = "menuStrip1";
            // 
            // menu_FirstPage
            // 
            this.menu_FirstPage.Name = "menu_FirstPage";
            this.menu_FirstPage.Size = new System.Drawing.Size(44, 21);
            this.menu_FirstPage.Text = "首页";
            // 
            // menu_PreviousPage
            // 
            this.menu_PreviousPage.Name = "menu_PreviousPage";
            this.menu_PreviousPage.Size = new System.Drawing.Size(56, 21);
            this.menu_PreviousPage.Text = "上一页";
            // 
            // menu_NextPage
            // 
            this.menu_NextPage.Name = "menu_NextPage";
            this.menu_NextPage.Size = new System.Drawing.Size(56, 21);
            this.menu_NextPage.Text = "下一页";
            // 
            // menu_LastPage
            // 
            this.menu_LastPage.Name = "menu_LastPage";
            this.menu_LastPage.Size = new System.Drawing.Size(44, 21);
            this.menu_LastPage.Text = "尾页";
            // 
            // menu_ClearLog
            // 
            this.menu_ClearLog.Name = "menu_ClearLog";
            this.menu_ClearLog.Size = new System.Drawing.Size(68, 21);
            this.menu_ClearLog.Text = "清空日志";
            // 
            // menu_PageInfo
            // 
            this.menu_PageInfo.Name = "menu_PageInfo";
            this.menu_PageInfo.Padding = new System.Windows.Forms.Padding(100, 0, 4, 0);
            this.menu_PageInfo.Size = new System.Drawing.Size(164, 21);
            this.menu_PageInfo.Text = "页码信息";
            // 
            // menu_LogManage
            // 
            this.menu_LogManage.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.menu_SaveLog,
            this.每页显示日志条数ToolStripMenuItem});
            this.menu_LogManage.Name = "menu_LogManage";
            this.menu_LogManage.Padding = new System.Windows.Forms.Padding(50, 0, 4, 0);
            this.menu_LogManage.Size = new System.Drawing.Size(114, 21);
            this.menu_LogManage.Text = "管理日志";
            // 
            // dataGridView1
            // 
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.dataGridView1.Location = new System.Drawing.Point(0, 25);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.RowTemplate.Height = 23;
            this.dataGridView1.Size = new System.Drawing.Size(703, 304);
            this.dataGridView1.TabIndex = 10;
            // 
            // menu_SaveLog
            // 
            this.menu_SaveLog.Name = "menu_SaveLog";
            this.menu_SaveLog.Size = new System.Drawing.Size(180, 22);
            this.menu_SaveLog.Text = "保存日志";
            // 
            // 每页显示日志条数ToolStripMenuItem
            // 
            this.每页显示日志条数ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.com_PageCount});
            this.每页显示日志条数ToolStripMenuItem.Name = "每页显示日志条数ToolStripMenuItem";
            this.每页显示日志条数ToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
            this.每页显示日志条数ToolStripMenuItem.Text = "每页显示日志条数";
            // 
            // com_PageCount
            // 
            this.com_PageCount.Items.AddRange(new object[] {
            "5",
            "10",
            "15",
            "20",
            "25",
            "30"});
            this.com_PageCount.Name = "com_PageCount";
            this.com_PageCount.Size = new System.Drawing.Size(121, 25);
            // 
            // UcLogManage
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Controls.Add(this.dataGridView1);
            this.Controls.Add(this.menuStrip1);
            this.Name = "UcLogManage";
            this.Size = new System.Drawing.Size(703, 329);
            this.menuStrip1.ResumeLayout(false);
            this.menuStrip1.PerformLayout();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.MenuStrip menuStrip1;
        private System.Windows.Forms.ToolStripMenuItem menu_PreviousPage;
        private System.Windows.Forms.ToolStripMenuItem menu_NextPage;
        private System.Windows.Forms.DataGridView dataGridView1;
        private System.Windows.Forms.ToolStripMenuItem menu_ClearLog;
        private System.Windows.Forms.ToolStripMenuItem menu_PageInfo;
        private System.Windows.Forms.ToolStripMenuItem menu_FirstPage;
        private System.Windows.Forms.ToolStripMenuItem menu_LastPage;
        private System.Windows.Forms.ToolStripMenuItem menu_LogManage;
        private System.Windows.Forms.ToolStripMenuItem menu_SaveLog;
        private System.Windows.Forms.ToolStripMenuItem 每页显示日志条数ToolStripMenuItem;
        private System.Windows.Forms.ToolStripComboBox com_PageCount;
    }
}

2 视图(View)

2.1 ViewServer

2.1.1 ViewServer.cs

using System;
using System.Windows.Forms;
using DemoThreeTimesHandshake.Controller;
using DemoThreeTimesHandshake.Model;
using DemoThreeTimesHandshake.Model.LogDS;

namespace DemoThreeTimesHandshake.View
{
    public partial class ViewServer : Form
    {
        public readonly LogUtil Log = new LogUtil();
        public Action EventStartServer;
        public Action EventDisplayLog;
        public ViewServer()
        {
            InitializeComponent();
            this.WindowState = FormWindowState.Maximized;
            var ucLogManage = new UcLogManage(Log) { Dock = DockStyle.Fill };
            EventDisplayLog += ucLogManage.DisplayResult;
            panel1.Controls.Add(ucLogManage);
            _ = new ServerController(this, new ServerModel());
        }

        private void menu_OpenClientForm_Click(object sender, EventArgs e) => new ViewClient().Show();

        private void menu_StartServer_Click(object sender, EventArgs e)
        {
            EventStartServer?.Invoke();
        }

        public void DisplayResult()
        {
            menu_StartServer.Enabled = false;
            this.Text = "服务器,状态:已启动,等待客户端连接...";
        }

    }
}

2.1.1 ViewServer.Designer.cs

namespace DemoThreeTimesHandshake.View
{
    partial class ViewServer
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.menuStrip1 = new System.Windows.Forms.MenuStrip();
            this.menu_StartServer = new System.Windows.Forms.ToolStripMenuItem();
            this.menu_OpenClientForm = new System.Windows.Forms.ToolStripMenuItem();
            this.panel1 = new System.Windows.Forms.Panel();
            this.menuStrip1.SuspendLayout();
            this.SuspendLayout();
            // 
            // menuStrip1
            // 
            this.menuStrip1.Font = new System.Drawing.Font("Microsoft YaHei UI", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.menu_StartServer,
            this.menu_OpenClientForm});
            this.menuStrip1.Location = new System.Drawing.Point(0, 0);
            this.menuStrip1.Name = "menuStrip1";
            this.menuStrip1.Size = new System.Drawing.Size(824, 30);
            this.menuStrip1.TabIndex = 10;
            this.menuStrip1.Text = "menuStrip1";
            // 
            // menu_StartServer
            // 
            this.menu_StartServer.Name = "menu_StartServer";
            this.menu_StartServer.Size = new System.Drawing.Size(102, 26);
            this.menu_StartServer.Text = "开启服务器";
            this.menu_StartServer.Click += new System.EventHandler(this.menu_StartServer_Click);
            // 
            // menu_OpenClientForm
            // 
            this.menu_OpenClientForm.Name = "menu_OpenClientForm";
            this.menu_OpenClientForm.Size = new System.Drawing.Size(134, 26);
            this.menu_OpenClientForm.Text = "打开客户端窗口";
            this.menu_OpenClientForm.Click += new System.EventHandler(this.menu_OpenClientForm_Click);
            // 
            // panel1
            // 
            this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.panel1.Location = new System.Drawing.Point(0, 30);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(824, 402);
            this.panel1.TabIndex = 11;
            // 
            // ViewServer
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(824, 432);
            this.Controls.Add(this.panel1);
            this.Controls.Add(this.menuStrip1);
            this.Name = "ViewServer";
            this.Text = "服务器,状态:未开启";
            this.menuStrip1.ResumeLayout(false);
            this.menuStrip1.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.MenuStrip menuStrip1;
        private System.Windows.Forms.ToolStripMenuItem menu_StartServer;
        private System.Windows.Forms.ToolStripMenuItem menu_OpenClientForm;
        private System.Windows.Forms.Panel panel1;
    }
}

2.2 ViewClient

2.2.1 ViewClient.cs

using System;
using System.Windows.Forms;
using DemoThreeTimesHandshake.Controller;
using DemoThreeTimesHandshake.Model;
using DemoThreeTimesHandshake.Model.LogDS;

namespace DemoThreeTimesHandshake.View
{
    public partial class ViewClient : Form
    {
        public EventHandler<ClientEventManage> EventManage;
        public Action EventDisplayLog;
        public readonly LogUtil LogUtil = new LogUtil();

        public ViewClient()
        {
            InitializeComponent();
            this.TopMost = true;
            _ = new ClientController(this, new ClientModel());
            var ucLogManage = new UcLogManage(LogUtil, nameof(Log.IP), nameof(Log.Port)) { Dock = DockStyle.Fill };
            EventDisplayLog += ucLogManage.DisplayResult;
            panel1.Controls.Add(ucLogManage);
        }

        private void menu_StartClient_Click(object sender, EventArgs e)
        {
            EventManage?.Invoke(this, new ClientEventManage(EEventType.Open));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            EventManage?.Invoke(this, new ClientEventManage(EEventType.Send, textBox1.Text));
        }

        public void DisplayResult(string ip, int port)
        {
            if (InvokeRequired)
            {
                Invoke(new EventHandler(delegate { DisplayResult(ip, port); }));
            }
            else
            {
                menu_StartClient.Enabled = false;
                this.Text = $"客户端,状态:已连接,IP = {ip},端口 = {port}";
            }
        }

    }

    public enum EEventType { Open, Send }

    public class ClientEventManage : EventArgs
    {
        public EEventType Type { get; set; }
        public string Message { get; set; }

        public ClientEventManage(EEventType type, string message)
        {
            Type = type;
            Message = message;
        }

        public ClientEventManage(EEventType type)
        {
            Type = type;
        }
    }
}

2.2.1 ViewClient.Designer.cs

namespace DemoThreeTimesHandshake.View
{
    partial class ViewClient
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.menuStrip1 = new System.Windows.Forms.MenuStrip();
            this.menu_StartClient = new System.Windows.Forms.ToolStripMenuItem();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.panel1 = new System.Windows.Forms.Panel();
            this.menuStrip1.SuspendLayout();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(210, 40);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(78, 21);
            this.button1.TabIndex = 5;
            this.button1.Text = "发送";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // menuStrip1
            // 
            this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.menu_StartClient});
            this.menuStrip1.Location = new System.Drawing.Point(0, 0);
            this.menuStrip1.Name = "menuStrip1";
            this.menuStrip1.Size = new System.Drawing.Size(793, 25);
            this.menuStrip1.TabIndex = 6;
            this.menuStrip1.Text = "menuStrip1";
            // 
            // menu_StartClient
            // 
            this.menu_StartClient.Name = "menu_StartClient";
            this.menu_StartClient.Size = new System.Drawing.Size(80, 21);
            this.menu_StartClient.Text = "启动客户端";
            this.menu_StartClient.Click += new System.EventHandler(this.menu_StartClient_Click);
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(35, 40);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(148, 21);
            this.textBox1.TabIndex = 7;
            // 
            // panel1
            // 
            this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.panel1.Location = new System.Drawing.Point(35, 99);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(731, 365);
            this.panel1.TabIndex = 8;
            // 
            // ViewClient
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(793, 494);
            this.Controls.Add(this.panel1);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.menuStrip1);
            this.MainMenuStrip = this.menuStrip1;
            this.Name = "ViewClient";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "客户端,状态:未连接";
            this.menuStrip1.ResumeLayout(false);
            this.menuStrip1.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.MenuStrip menuStrip1;
        private System.Windows.Forms.ToolStripMenuItem menu_StartClient;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Panel panel1;
    }
}

3 控制器(Controller)

3.1 ServerController

using System.Net.Sockets;
using DemoThreeTimesHandshake.Model;
using DemoThreeTimesHandshake.Tool;
using DemoThreeTimesHandshake.View;


namespace DemoThreeTimesHandshake.Controller
{
    public class ServerController
    {
        private readonly ViewServer _view;
        private readonly ServerModel _model;

        public ServerController(ViewServer view, ServerModel model)
        {
            _view = view;
            _model = model;
            _view.EventStartServer += OnEventStartServer;
            _model.EventAddLog += OnAddLog;
        }

        private void OnEventStartServer()
        {
            _model.OpenServer();
            _view.DisplayResult();
        }

        private void OnAddLog(TcpClient client, Config.MyEnum type, string description)
        {
            Utility.GetClientInfo(client, out string ip, out int port);
            _view.Log.AddLog(ip, port, type, description);
            _view.EventDisplayLog?.Invoke();
        }
    }
}

3.2 ClientController

using System.Net.Sockets;
using System.Threading.Tasks;
using DemoThreeTimesHandshake.Model;
using DemoThreeTimesHandshake.View;


namespace DemoThreeTimesHandshake.Controller
{
    public class ClientController
    {
        private readonly ViewClient _view;
        private readonly ClientModel _model;

        public ClientController(ViewClient view, ClientModel model)
        {
            _view = view;
            _model = model;
            _view.EventManage += OnEventStartClient;
            _model.EventAddLog += OnAddLog;
        }

        private void OnEventStartClient(object obj, ClientEventManage e)
        {
            switch (e.Type)
            {
                case EEventType.Open:
                    new Task(() =>
                    {
                        _model.OpenServer();
                        _model.GetClientInfo(out string ip, out int port);
                        _view.DisplayResult(ip, port);
                    }).Start();
                    break;
                case EEventType.Send:
                    _model.Send(e.Message);
                    break;
            }
        }

        private void OnAddLog(TcpClient client, Config.MyEnum type, string description)
        {
            _model.GetClientInfo(out string ip, out int port);
            _view.LogUtil.AddLog(ip, port, type, description);
            _view.EventDisplayLog?.Invoke();
        }
    }
}

4 工具类

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;

namespace DemoThreeTimesHandshake.Tool
{
    public static class Utility
    {

        private static readonly Dictionary<string, string> descriptionCache = new Dictionary<string, string>();

        /// <summary>
        /// 获取属性/枚举成员的Description
        /// </summary>
        public static string GetPropertyDescription<T>(string propertyName)
        {
            string cacheKey = $"{typeof(T).FullName}.{propertyName}";
            if (descriptionCache.TryGetValue(cacheKey, out string description))
            {
                return description;
            }

            Type type = typeof(T);
            PropertyInfo property = type.GetProperty(propertyName);
            if (property != null)
            {
                DescriptionAttribute descriptionAttribute = property.GetCustomAttribute<DescriptionAttribute>();
                if (descriptionAttribute != null)
                {
                    description = descriptionAttribute.Description;
                    descriptionCache[cacheKey] = description;
                    return description;
                }
            }

            FieldInfo field = type.GetField(propertyName);
            if (field != null)
            {
                DescriptionAttribute descriptionAttribute = field.GetCustomAttribute<DescriptionAttribute>();
                if (descriptionAttribute != null)
                {
                    description = descriptionAttribute.Description;
                    descriptionCache[cacheKey] = description;
                    return description;
                }
            }

            return null;
        }

        /// <summary>
        /// 设置DataGridView样式
        /// </summary>
        public static void SetDgvStyle(DataGridView table)
        {
            try
            {
                table.ClearSelection();
                //int index = dgvStandard.CurrentCell.RowIndex;//获取选中行
                table.MultiSelect = false; //不可多选
                table.AllowUserToAddRows = false; //设置不显示添加行
                table.AllowUserToDeleteRows = false; //设置不允许删除行
                table.AllowUserToResizeColumns = false; //设置列不可调整
                table.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; //列名居中
                table.AllowUserToResizeRows = false; //设置行不可调整
                table.RowHeadersVisible = false; //设置表头不显示行标题
                table.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; //列填充控件显示区域
                table.CausesValidation = false; //焦点
                table.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single; //边框样式
                table.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; //列高调整

                table.RowsDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; //单元格内容居中
                table.ReadOnly = false; //只读设置
                table.RowHeadersWidth = 4; //列宽设置(按照权重设置时需要先添加列)
                table.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders; //设置列表头不可调整
                table.RowTemplate.Height = 28; //设置行高
                table.ScrollBars = ScrollBars.Vertical; //显示垂直滚动条
                table.TabStop = false; //设置无Tab焦点
                table.VirtualMode = true; //设置可进行数据管理
                //table.Rows[lastTableHeadRow].Frozen = true;//冻结指定行

                for (var i = 0; i < table.Columns.Count; i++)
                {
                    //table.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable; //禁止点击列名排序
                    //table.Columns[i].FillWeight = 1; //按权重分配列宽

                    //设置图像列的布局
                    //var column = table.Columns[i] as DataGridViewImageColumn;
                    //if (column != null)
                    //{
                    //    column.ImageLayout = DataGridViewImageCellLayout.Zoom;
                    //}
                }
            }
            catch (Exception)
            {
                // ignored
            }
        }

        /// <summary>
        /// 获取客户端信息
        /// </summary>
        public static void GetClientInfo(TcpClient client, out string ip, out int port)
        {
            try
            {
                IPEndPoint clientEndPoint = (IPEndPoint)client.Client.RemoteEndPoint;
                ip = clientEndPoint.Address.ToString();
                port = clientEndPoint.Port;
            }
            catch
            {
                ip = "";
                port = 0;
            }
        }

        /// <summary>
        /// 深度拷贝
        /// </summary>
        public static T DeepCopy<T>(this T obj)
        {
            if (!obj.GetType().IsSerializable)
            {
                return default(T);
            }
            using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(ms, obj);
                ms.Position = 0;

                return (T)formatter.Deserialize(ms);
            }
        }

        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static long GetTimeLong()
        {
            long unixTimestampMs = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds;
            return unixTimestampMs;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2321054.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式算法:Paxos Raft 两种共识算法

1. Paxos算法 Paxos算法是 Leslie Lamport&#xff08;莱斯利兰伯特&#xff09;在 1990 年提出的一种分布式系统共识算法。也是第一个被证明完备的共识算法&#xff08;前提是不存在恶意节点&#xff09;。 1.1 简介 Paxos算法是第一个被证明完备的分布式系统共识算法。共识…

什么是数据库监控

数据库监控是一个综合的过程&#xff0c;涉及观察、分析和优化组织内数据库的性能、运行状况和可用性。通过持续跟踪查询执行时间、CPU使用率、内存消耗和存储I/O等指标&#xff0c;数据库监控使管理员能够主动识别和解决潜在问题。这种对数据库操作的实时可见性对于确保应用程…

Java学习总结-泛型

什么是泛型&#xff1f; 定义 类、接口、方法时&#xff0c;同时声明了一个或多个类型变量&#xff08;如&#xff1a;<E>&#xff09;&#xff0c;称为泛型类、泛型接口、泛型方法、他们统称为泛型。public class ArrayList<E>{ }。 有什么作用呢&#xf…

基于深度学习的相位调制算法步骤

1.构建网络结构 2.制作数据集 3.训练网络 4.引入评价指标 5.迭代优化 总结 通过以上步骤&#xff0c;可以实现基于深度学习的相位调制算法&#xff1a; 使用 U-Net 构建神经网络。 生成数据集并训练网络。 使用训练好的网络预测相位分布。 通过相关系数 γ 评估调制效果&…

Go语言的基础类型

一基础数据类型 一、布尔型&#xff08;Bool&#xff09; 定义&#xff1a;表示逻辑真 / 假&#xff0c;仅有两个值&#xff1a;true 和 false内存占用&#xff1a;1 字节使用场景&#xff1a;条件判断、逻辑运算 二、数值型&#xff08;Numeric&#xff09; 1. 整数类型&…

动力保护板测试仪:电池安全的坚实守护者

在新能源技术日新月异的今天&#xff0c;电池作为各类电子设备的心脏&#xff0c;其安全性与可靠性成为了行业内外关注的焦点。而动力保护板&#xff0c;作为电池系统中的重要组成部分&#xff0c;承担着精准调控电池充放电、防止电池过充、过放、短路等危险情况的重任。然而&a…

Lineageos 22.1(Android 15)制定应用强制横屏

一、前言 有时候需要系统的某个应用强制衡平显示&#xff0c;不管他是如何配置的。我们只需要简单的拿到top的Task下面的ActivityRecord&#xff0c;并判断包名来强制实现。 二、调整wms com.android.server.wm.DisplayRotation /*** Given an orientation constant, return…

SpringBoot-3-JWT令牌

目录 引入 引入依赖 拦截器 创建工具类 创建拦截器的包及拦截器 注册拦截器 修改一下登录成功后token的代码 测试 引入 试想一下&#xff0c;以上我们的访问都是直接访问对应的接口。比如说用户登录的时候就访问登录的接口。 那么如果有人他不访问你的登录接口&#…

git使用经验(一)

git使用经验&#xff08;一&#xff09; 我之前已经下载了别人的代码&#xff0c;我想在此基础上进行修改&#xff0c;并移动到自己的私有仓库&#xff0c;方便上传到自己的私有仓库自己进行版本控制 git clone下来别人的代码&#xff0c;删除有关git的隐藏文件 进入到自己的…

文件上传的小点总结

1.文件上传漏洞 服务器端脚本语言对上传文件没有严格的验证和过滤&#xff0c;就可以给攻击者上传恶意脚本文件的可能。 文件上传检测绕过&#xff1a; 简单思路&#xff1a;&#xff08;这里以前端上传图片为例&#xff09; ①开启phpstudy&#xff0c;启动apache即可&…

基于WebRtc,GB28181,Rtsp/Rtmp,SIP,JT1078,H265/WEB融合视频会议接入方案

智能融合视频会议系统方案—多协议、多场景、全兼容的一站式视频协作平台 OvMeet,LiveMeet针对用户​核心痛点实现功能与用户价值 &#xff0c;Web平台实现MCU多协议&#xff0c;H265/H264等不同编码监控&#xff0c;直播&#xff0c;会议&#xff0c;调度资源统一融合在一套界…

基于漂浮式海上风电场系统的浮式风力发电机matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于漂浮式海上风电场系统的浮式风力发电机matlab仿真&#xff0c;通过MATLAB数值仿真对浮式风力发电机的性能做模拟与仿真。 2.系统仿真结果 3.核心程序与模型 版本&#x…

深入探索ArkUI中的@LocalBuilder装饰器:构建高效可维护的UI组件

在ArkUI框架中&#xff0c;组件化开发是提升代码复用性和维护性的关键手段。随着项目复杂度的增加&#xff0c;开发者常常面临如何在保持组件封装性的同时&#xff0c;灵活处理组件内部逻辑的问题。传统的Builder装饰器虽然提供了强大的自定义构建能力&#xff0c;但在某些场景…

快速查询手机是否处于联网状态?

手机是否处于联网状态对于我们日常生活中的沟通、工作和娱乐都至关重要。有时候我们需要迅速了解一个手机号码的在网状态&#xff0c;例如是正常使用、停机、不在网等。而要实现这一功能&#xff0c;我们可以利用挖数据平台提供的在线查询工具&#xff0c;通过API接口来查询手机…

使用 .NET Core 的本地 DeepSeek-R1

使用 .NET 在我的 MacBook Pro 上与当地 LLM 聊天的历程。 如今&#xff0c;只需使用浏览器即可轻松使用 ChatGPT 或其他 genAI。作为开发人员&#xff0c;我们可以通过直接集成 OpenAI API 等来做更复杂的事情。如果我们想在自己的机器上运行 LLM&#xff0c;只是为了找人聊天…

SQL Server查询计划操作符(7.3)——查询计划相关操作符(11)

7.3. 查询计划相关操作符 98&#xff09;Table Scan&#xff1a;该操作符从查询计划参数列确定的表中获取所有数据行。如果其参数列中出现WHERE:()谓词&#xff0c;则只返回满足该谓词的数据行。该操作符为逻辑操作符和物理操作符。该操作符具体如图7.3-98节点1所示。 图 7.3-…

xy轴不等比缩放问题——AUTOCAD c#二次开发

在 AutoCAD .net api里&#xff0c;部分实体&#xff0c;像文字、属性、插入块等&#xff0c;是不支持非等比缩放的。 如需对AutoCAD中图形进行xyz方向不等比缩放&#xff0c;则需进行额外的函数封装。 选择图元&#xff0c;指定缩放基准点&#xff0c;scaleX 0.5, scaleY …

【原创首发】开源基于AT32 SIP/VOIP电话

前言 本次为了反馈各位粉丝的关注&#xff0c;特此分享 AT32_VOIP 工程&#xff0c;此功能其实跟我之前发过的《STM32F429的VOIP功能》是一样的&#xff0c;只是用了AT32F437。 其实那个工程是一个比较Demo中的Demo&#xff0c;很多功能和硬件依赖性太大了。后面项目中发现AT…

一篇文章入门Python Flask框架前后端数据库开发实践(pycharm在anaconda环境下)

Python Flask 是一个轻量级的 Web 应用框架&#xff0c;也被称为微框架。它以简洁、灵活和易于上手的特点而受到开发者的喜爱。 核心特点 轻量级&#xff1a;Flask 核心代码简洁&#xff0c;仅包含 Web 开发的基本功能&#xff0c;不强制使用特定的数据库、模板引擎等&#xf…

AI+金融 应用 使用DeepSeek、Qwen等大模型输入自然语言,得到通达信等行情软件公式代码,导入后使用

AI金融 应用 使用DeepSeek、Qwen等大模型输入自然语言&#xff0c;得到通达信等行情软件公式代码&#xff0c;导入后使用。不会编程&#xff0c;也能行情软件中实现个性化条件选股&#xff0c;个性化技术指标。 AIbxm低估值趋势选股策略&#xff0c;参考提示词&#xff1a; 编…