当前位置: 首页 > article >正文

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

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.kler.cn/a/593177.html

相关文章:

  • maven项目进行单元测试详细教程
  • 【论文阅读】Explainable Early Stopping for Action Unit Recognition
  • 在linux系统中运行window应用,并使用系统显卡能力的实现方案
  • 数据结构之链表(单链表)
  • 函数的介绍
  • QtitanRibbon在医疗场景中的精细化功能应用
  • ollama不安装到c盘,安装到其他盘
  • (2025|ICLR|华南理工,任务对齐,缓解灾难性遗忘,底层模型冻结和训练早停)语言模型持续学习中的虚假遗忘
  • 免费实用工具,wps/office/永中通吃!
  • oracle 基础知识事务的特性
  • Tomcat 与 Java 环境变量配置简明教程
  • PHP序列化漏洞
  • Python散点图(Scatter Plot):高阶分析、散点图矩阵、三维散点图及综合应用
  • 信息检索 information retrieval--lab练习(更新中)
  • Linux信号的处理
  • 【蓝桥杯速成】| 7.01背包练习生
  • 第5章:Docker镜像管理实战:构建、推送与版本控制
  • 【人工智能-前端OpenWebUI】--图片显示
  • 详细介绍GetDlgItem()
  • 器材借用管理系统详细设计基于Spring Boot-SSM