Winfrom下的socket TCP基础通信

大家好,我是你们的好朋友程序员:铭文

先简单的说下:好久没写通信了最近几年一直在写一些业务的接口程序。处理一些数据业务,但是根据工作需要:我现
在要写一个和下位机做这个时时通信的这样一个程序,目的主要是简历这个连接进行和下位机的交互,数据的传递:

Socket基础:

其实我的理解就是:Socket就是一个最最基础的通信而已。它是通过服务的端口来进行连接。连接互联网的机器都有自己的ip,也就是我们自己的服务器ip但是我们大家都连接到 Internet网 以后,我们就是可以通过这个socket 来进行通信。我们程序猿也都知道:网络通信的工作的7层吧:

1. 最基础的物理层:有 线路,光纤网线这些东西。
2. 数据链路层: 这就是我们内网的以太网。就是一个代表。
3. 网络传输层:这一层比较复杂:数据链路层的数据在这一层被转换为数据包,数据包这些就是分段组合。然后通过网络设备传送到另外一台网络设备的:TCP/IP,和地址解析等等感兴趣的可以自己去搜索下,
4. 运输层: 这就就包含我们这次要实现的 :TCP和UDP
5. 会话层: 这一层非常简单:用我们前后端分离的开发模式说就是:你前端拿了后端的api接口 return的数据。我来进行数据的渲染哈哈;还有 有2个页面之间的session会话对象,
6 表示层:
,比如我们经常使用的QQ就是socket 通信的一种:
在这里插入图片描述
打开QQ的设置就可以看到,这里我们可以看到服务器类型这块分为2个:UDP,TCP
7 应用层: 这个就代表的是应用的本身了。比如qq。通过应用程序的通讯服务的就是我们最容易理解的应用层。

UDP的介绍与应用:

我这边简单的说下:
udp就是用户数据报告交互协议,记住的关键单就是:不是面向连接的。不可靠的数据传输,udp的可靠性比较差。它可以把应用程序传给服务层(ip)的数据发送出去,但是不能保证到达。就是我们经常会出现的。丢数据,丢包,数据不稳定,udp是会经常出现的、
举一个简单的事例:
我们经常使用qq电话视频。这个时候如果信号差的时候经常会出现卡顿。但是连接还是有的,但是视频信号用的就是udp,我做的就是可以保证,视频信号高效率的发出,至于你接收端的接收等等不在我考虑的范围内。就是我们“ping” 命令来测试两台主机之间 tcp/ip 通信,其实“ping”命令的原理就是向服务主机发送UDP数据包,然后服务主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。就是这么简单,

TCP的介绍与应用 TCP/IP(Transmission Control Protocol/Internet Protocol 传输控制协议/网间协议) :

这个需要着重说下,因为目前我们使用的也是这个:
传输控制协议 tcp:可以2个主机之间交互反馈。也就是我们协议之间理解的一种“心跳”互动,交互的概念。实现的比如,我们做的交互,一段时间没有回复,定义的规则下我可以再次的发送消息。等另外还可以做到负责恢复,这个我没用过,我也是看书上写的。
网间协议 IP:可以进行传输的数据包的分割组装。我们项目中就出现了一个这个的问题:我们的环境是写了一个python 来读取别人系统的数据,然后把数据通过咱们现在说的这个tcp传输到下位机上面。下位机然后再把数据传输到。winfrom上面就是我们上位机的一个程序上面,我主要负责的就是下位机数据的处理,但是这个时候,下位机给我提交的数据就出现了一个问题,经常丢数据,丢包,丢前面或者丢后面,后来证实了。他的那个下位机的单片机传输的数据只能包含2k之内,不然经常丢数据,这个时候就要通过网间协议来,把数据进行分割。重新储存了。
tcp的特点和定义
tcp和udp正好相反:是面向连接、可靠的字节流服务
不废话了上源码:(这是一个winfrom的程序)
客户端代码:

public partial class frmMainSender : Form
    {
        private Socket _socketSend = null;
        private Thread _watchThread = null;
        private Thread _heartBeatThread = null;
        private tm.Timer _timer = null;

        public frmMainSender()
        {
            InitializeComponent();
            this.Load += FrmMainSender_Load;
        }

        private void FrmMainSender_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(txtIP.Text) || string.IsNullOrEmpty(txtPort.Text))
                {
                    MessageBox.Show("IP及端口不可空!");
                    return;
                }
                //IPAddress 类包含计算机在网络上的 IP 地址,它主要提供网际协议地址(IP)
                IPAddress ipAdd = IPAddress.Parse(txtIP.Text);
                _socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //ReceiveTimeout 属性确定Read方法在能够接受数据之前保持阻塞状态的时间量
                _socketSend.ReceiveTimeout = 10000;
                //超时时间量
                _socketSend.SendTimeout = 10000;
                _socketSend.Connect(new IPEndPoint(ipAdd, Int32.Parse(txtPort.Text)));

                WriteLog("连接服务器成功!");
                btnStartServer.Enabled = false;

                _watchThread = new Thread(Received);
                _watchThread.IsBackground = true;
                _watchThread.Start();

                _heartBeatThread = new Thread(HeartBeat);
                _heartBeatThread.IsBackground = true;
                _heartBeatThread.Start();
            }
            catch (Exception)
            {
            }
        }

        private void Received()
        {
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[1024 * 1024 * 3];
                    int length = _socketSend.Receive(buffer);
                    if (length == 0)
                    {
                        break;
                    }
                    string str = Encoding.UTF8.GetString(buffer, 0, length);

                    if (str.ToLower() == "heartbeat")
                    {
                        WriteLog("客户端---接收--检测心跳包!");
                        continue;
                    }
                    else if (str.ToLower() == "1")
                    {
                        WriteLog("接收端接收成功!");
                        continue;
                    }
                    txtReceiveData.Text = str;
                }
                catch (Exception)
                {
                }
            }
        }


        private void HeartBeat()
        {
            _timer = new tm.Timer(3000);
            _timer.Elapsed += _timer_Elapsed;
            _timer.Start();
        }


        private void _timer_Elapsed(object sender, tm.ElapsedEventArgs e)
        {
            try
            {
                WriteLog("客户端---发送---检测心跳包!");
                byte[] buffer = Encoding.UTF8.GetBytes("HeartBeat");
                _socketSend.Send(buffer);
            }
            catch (Exception)
            {

            }

        }

        private void btnStopServer_Click(object sender, EventArgs e)
        {
            if (_socketSend == null) return;
            if (!_socketSend.Connected) return;

            try
            {
                _heartBeatThread.Abort();
                _timer.Stop();
                _timer = null;
                _socketSend.Shutdown(SocketShutdown.Both);


            }
            catch (Exception)
            {
            }

            try
            {
                _socketSend.Close();
            }
            catch (Exception)
            {
            }

            btnStartServer.Enabled = true;
            WriteLog("服务已关闭!");
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            try
            {
                byte[] buffer = Encoding.UTF8.GetBytes(txtBase64Data.Text);
                _socketSend.Send(buffer);
                WriteLog("已发送数据!");
            }
            catch (Exception)
            {
            }
        }

        private void btnBase64_Click(object sender, EventArgs e)
        {
            byte[] bytes = Encoding.Default.GetBytes(txtReceiveData.Text);
            txtBase64Data.Text = Convert.ToBase64String(bytes);
        }

        private void WriteLog(string message)
        {
            txtLogs.AppendText(DateTime.Now.ToString("HH:mm:ss.fff") + "----" + message + "\r\n");
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            txtReceiveData.Text = "";
            txtBase64Data.Text = "";
        }

        private void btnClearLog_Click(object sender, EventArgs e)
        {
            txtLogs.Clear();
        }
    }

服务器端代码:

public partial class frmMainReceiver : Form
    {
        private Socket _socketSend = null;
        //定义一个集合,存储客户端信息
        static Dictionary<string, Socket> clientConnectionItems = new Dictionary<string, Socket> { };
        private tm.Timer _timer = null;
        private Thread _heartBeatThread = null;
        private Thread _watchThread = null;
        static Socket _socketWatch = null;

        public frmMainReceiver()
        {
            InitializeComponent();
            this.Load += FrmMainReceiver_Load;
        }

        private void FrmMainReceiver_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(txtIP.Text) || string.IsNullOrEmpty(txtPort.Text))
                {
                    MessageBox.Show("IP及端口不可空!");
                    return;
                }

                IPAddress ipAdd = IPAddress.Any;
                //new Socket 实例
                _socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //绑定下
                _socketWatch.Bind(new IPEndPoint(ipAdd, Int32.Parse(txtPort.Text)));
                //套接口并监听申请的连接
                _socketWatch.Listen(100);

                WriteLog("服务已启动!");

                btnStartServer.Enabled = false;
				//线程
                _watchThread = new Thread(Listen);
                _watchThread.IsBackground = true;
                _watchThread.Start(_socketWatch);

                _heartBeatThread = new Thread(HeartBeat);
                _heartBeatThread.IsBackground = true;
                _heartBeatThread.Start();
            }
            catch (Exception ec) { }
        }

        private void HeartBeat()
        {
            _timer = new tm.Timer(5000);
            _timer.Elapsed += _timer_Elapsed;
            _timer.Start();
        }


        private void _timer_Elapsed(object sender, tm.ElapsedEventArgs e)
        {
            string[] keys = new string[clientConnectionItems.Keys.Count];
            clientConnectionItems.Keys.CopyTo(keys, 0);

            foreach (string key in keys)
            {
                Socket socket = clientConnectionItems[key];
                if (socket.Poll(10000, SelectMode.SelectRead))
                {
                    WriteLog(key + "---已断开连接!");
                    clientConnectionItems.Remove(key);
                    continue;
                }
                byte[] buffer = Encoding.UTF8.GetBytes("HeartBeat");
                socket.Send(buffer);


                WriteLog("接收端--向" + key + "-发送---检测心跳包!");
            }
        }

        private void Listen(object o)
        {
            try
            {
                Socket socketWatch = o as Socket;
                while (true)
                {
                    _socketSend = socketWatch.Accept();//等待接收客户端连接

                    //客户端网络结点号  
                    string remoteEndPoint = _socketSend.RemoteEndPoint.ToString();
                    clientConnectionItems.Add(remoteEndPoint, _socketSend);

                    WriteLog(remoteEndPoint + "连接成功!");

                    Thread thread = new Thread(ReceiveData);
                    thread.IsBackground = true;
                    thread.Start(_socketSend);
                }
            }
            catch (Exception e)
            {

            }

        }

        private void ReceiveData(object o)
        {
            try
            {
                Socket socketClient = o as Socket;
                while (true)
                {
                    byte[] buffer = new byte[1024 * 1024 * 3];
                    int length = socketClient.Receive(buffer);
                    if (length == 0)
                    {                    
                        continue;
                    }

                    string strMsg = Encoding.UTF8.GetString(buffer, 0, length);// 将接受到的字节数据转化成字符串;

                    txtReceiveData.Text = strMsg;

                    if (strMsg.ToLower() == ("heartbeat"))
                    {
                        WriteLog("接收端---接收来自" + socketClient.RemoteEndPoint.ToString() + "---检测心跳包!");
                        byte[] bufferBack = Encoding.UTF8.GetBytes("HeartBeat");
                        socketClient.Send(bufferBack);
                        continue;
                    }                   

                    byte[] outputb = Convert.FromBase64String(txtReceiveData.Text.Replace(' ', '+'));
                    txtNoBase64Data.Text = Encoding.Default.GetString(outputb);

                    WriteLog("接收端---接收到数据!");
                    //接收完数据后向客户端发送数据接收成功标志
                    socketClient.Send(Encoding.UTF8.GetBytes("1"));
                }
            }
            catch (Exception e)
            {
            }
        }

        private void WriteLog(string message)
        {
            txtLogs.AppendText(DateTime.Now.ToString("HH:mm:ss.fff") + "----" + message + "\r\n");
        }

        private void btnStopServer_Click(object sender, EventArgs e)
        {
            if (_socketSend == null) return;
            if (!_socketSend.Connected) return;

            try
            {
                _timer.Stop();
                _timer = null;
                _heartBeatThread.Abort();
                _watchThread.Abort();
                _socketSend.Shutdown(SocketShutdown.Both);
                _socketWatch.Shutdown(SocketShutdown.Both);
                clientConnectionItems.Clear();
            }
            catch (Exception)
            {
            }

            try
            {
                _socketSend.Close();
                _socketWatch.Close();
            }
            catch (Exception)
            {
            }

            btnStartServer.Enabled = true;
            WriteLog("服务已关闭!");
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            txtReceiveData.Text = "";
            txtNoBase64Data.Text = "";
        }

        private void btnClearLog_Click(object sender, EventArgs e)
        {
            txtLogs.Clear();
        }
    }

以上的就是 socket tcp 的双方的交互验证
希望大家又不懂的地方可以留言。我们互相交流,有欠妥的地方,也希望大家指出来

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 在 Windows Forms 应用程序中使用套接字通信需要使用 .NET Framework 中的 System.Net.Sockets 命名空间。下面是一个简单的例子,展示了如何使用套接字来实现客户端/服务器通信: 1. 在 Windows Forms 项目中添加对 System.Net.Sockets 命名空间的引用。 2. 在窗体的代码文件中声明一个 Socket 变量,用于存储套接字。 3. 使用 Socket 类的构造函数来创建一个新的 Socket 实例,并指定使用的协议 (如 TCP 或 UDP) 和地址族 (如 IPv4 或 IPv6)。 4. 对于客户端,使用 Socket 实例的 Connect 方法来连接到服务器。对于服务器,使用 Socket 实例的 Bind 方法来绑定到特定的地址和端口,并使用 Listen 方法来开始侦听连接请求。 5. 对于服务器,使用 Accept 方法来接受客户端的连接请求。对于客户端和服务器,使用 Send 和 Receive 方法来发送和接收数据。 6. 当通信完成时,使用 Socket 实例的 Close 方法来关闭套接字。 下面是一个使用 TCP 协议的示例,展示了如何在客户端和服务器之间进行简单的文本通信: 客户端代码: ``` using System; using System.Net; using System.Net.Sockets; using System.Text; namespace Client { ### 回答2: 在WinForm中实现Socket通讯可以通过以下步骤: 第一步是创建一个WinForm应用程序,可通过Visual Studio的模板创建一个新的WinForm项目。 第二步是添加一个Socket控件,可以在工具箱中找到并将其拖放到窗体上。然后,设置Socket的属性,如IP地址和端口号。 第三步是在窗体加载时,创建一个Socket,并连接到指定的服务端。可以使用Socket类的Connect方法来实现连接。 第四步是设置Socket的事件处理程序。可以为Socket控件的Received事件添加事件处理程序,在该处理程序中可以接收从服务端发送来的数据。 第五步是实现数据的发送。可以通过Socket的Send方法来向服务端发送数据,数据可以是字符串或字节数组。 第六步是处理Socket的关闭。可以在窗体的Closing事件中关闭Socket连接,以确保在关闭应用程序时释放资源。 最后,可以根据具体需求对Socket通讯进行扩展和优化,例如使用异步操作来提高通讯性能,处理异常情况等等。 总结起来,要在WinForm中实现Socket通讯,首先需要创建一个WinForm应用程序,然后添加和配置Socket控件,设置事件处理程序,发送和接收数据,并在适当的时候关闭Socket连接。 ### 回答3: 在WinForm中实现Socket通讯步骤如下: 1. 引入命名空间: 在项目中引入System.Net.Sockets命名空间,该命名空间包含了Socket相关的类和方法。 2. 创建Socket对象: 使用Socket类的构造函数创建一个Socket对象,指定通讯协议、地址族和通信类型。例如,可以使用以下代码创建一个TCP/IP协议的Socket对象: ``` Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ``` 3. 绑定Socket: 通过调用Socket对象的Bind方法,将Socket对象绑定到一个本地IP地址和端口号。例如,可以使用以下代码将Socket绑定到本地IP地址和端口号8888: ``` IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 8888); socket.Bind(ipEndPoint); ``` 4. 监听连接: 使用Socket对象的Listen方法开始监听连接请求。例如,可以使用以下代码开始监听连接请求: ``` socket.Listen(10); ``` 5. 接受连接: 使用Socket对象的Accept方法接受连接请求,并返回一个新的Socket对象用于通信。例如,可以使用以下代码接受连接请求并返回一个新的Socket对象: ``` Socket clientSocket = socket.Accept(); ``` 6. 发送和接收数据: 使用新返回的Socket对象进行数据的发送和接收操作。可以使用Socket对象的Send和Receive方法发送和接收字节数据。例如,可以使用以下代码发送数据: ``` byte[] data = Encoding.ASCII.GetBytes("Hello, World!"); clientSocket.Send(data); ``` 7. 关闭连接: 使用Socket对象的Close方法关闭连接,并释放相关资源。例如,可以使用以下代码关闭连接: ``` clientSocket.Close(); ``` 以上就是在WinForm中实现Socket通讯的一般步骤。请根据自己的实际需求和业务逻辑进行相应的调整和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个武术猴子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值