C# Socket通信

一、通信协议 TCP/UDP

TCP
传输控制协议Transmission Control Protocol
是一种面向连接的、可靠的、基于字节流的运输层通信协议,在简化的计算机网络OSI模型中,它完成传输层所指定的功能。优点传输安全,缺点效率相对低。

UDP
用户数据报协议 User Datagram Protocol
UDP是一个简单的面向无连接的,不可靠的数据报的传输层(transport layer)协议。优点传输速度快,缺点不安全。

 

二、SOCKET

 

  socket(套接字)可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。Socket是面向客户/服务器模型而设计的。通信的一方扮演客户机的角色,另一方扮演服务器的角色。服务器在运行中一直监听套接字指定的传输层端口,并等待着客户机的连接请求。当服务器端收到客户机发来的连接请求以后,服务器会接受客户机的连接请求,双方建立连接后,就可进行数据的传递。服务器端可以一对多。

支持TCP/UDP传输协议
IP找设备,port端口找到服务器上要通讯的程序。
建立socket对象,负责收发数据

 

三、SOCKET代码实现

客户端

 

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

namespace WindowsFormsApp7
{
    public partial class Form1 : Form
    {
        private Socket socket;
        Encoding encoding = Encoding.Unicode;
        public Form1()
        {
            InitializeComponent();
            load();

        }

        /// <summary>
        /// 加载
        /// </summary>
        private void load()
        {
            //1.获取本地网络分配给你的IP
            IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());
            //第二步:
            foreach (var item in hostEntry.AddressList)
            {
                //3.判断是否是协议版本V4
                if (item.AddressFamily == AddressFamily.InterNetwork)
                {
                    cB_IPs.Items.Add(item);
                }
            }
            //添加本机IP
            cB_IPs.Items.Add("127.0.0.1");
            cB_IPs.Items.Add("192.168.110.96");
            cB_IPs.SelectedIndex = 0;//默认选中0个对象
        }

        /// <summary>
        /// 连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button2_Click(object sender, EventArgs e)
        {
            //第一步:初始化套接字对象
            socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
            try
            {
                //第二步:连接
                socket.Connect(cB_IPs.Text,(int)numericUpDown1.Value);
                MessageBox.Show("连接成功!");
                Task.Run(() =>
                {
                    while (true)
                    {
                        //监测服务器是否下线
                        try
                        {
                            bool yes = socket.Poll(1, SelectMode.SelectRead);
                            if (yes)
                            {
                                MessageBox.Show("服务器已下线!");
                                continue;
                            }
                            Reception();
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show("服务器连接异常!"+ex.Message);
                            return;
                        }
                       
                    }
                });
            }
            catch(Exception ex)
            {
                //连接失败
                MessageBox.Show($"连接失败:{ex}");
            }

        }
        /// <summary>
        /// 断开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button1_Click(object sender, EventArgs e)
        {
            if (socket != null && socket.Connected)
            {
                socket.Close();
                MessageBox.Show("断开连接");
            }
        }

        /// <summary>
        /// 发送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button3_Click(object sender, EventArgs e)
        {
            //1.判断连接状态
            if (socket != null && socket.Connected)
            {
                //2.字符串转换二进制
                byte[] data = encoding.GetBytes(richTextBox2.Text);
                try
                {
                    //3.发送
                    socket.Send(data);
                }
                catch (Exception ex)
                {

                    MessageBox.Show($"发送失败:{ex}");
                }
            }
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        public void Reception()
        {
            
            byte[] data = new byte[1024 * 2];
            try
            {
                //接收
                int length = socket.Receive(data);
                //判断是否有发送字节
                if (length > 0)
                {
                    richTextBox1.Invoke(new Action(() => {
                        richTextBox1.AppendText($" [{DateTime.Now.ToString("HH:mm:ss")}]:{encoding.GetString(data, 0, length)}" + Environment.NewLine);
                    }));

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"接收失败:{ex}");
            }
  
        }

        /// <summary>
        /// 打开服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button4_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.Show();
        }
    }
}

 

服务端

 

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp7
{
    public partial class Form2 : Form
    {
        //服务器套接字
        private Socket socket;
        //客户端连接
        List<Socket> sockets = new List<Socket>();
        //服务器连接标识
        bool connectingFlag;

        Encoding encoding = Encoding.Unicode;
        public Form2()
        {
            InitializeComponent();
            load();
        }

        private void Label3_Click(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 加载
        /// </summary>
        private void load()
        {
            //1.获取本地网络分配给你的IP
            System.Net.IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());
            //第二步:
            foreach (var item in hostEntry.AddressList)
            {
                //3.判断是否是协议版本V4
                if (item.AddressFamily == AddressFamily.InterNetwork)
                {
                    cB_IPs.Items.Add(item);
                }
            }
            //添加本机IP
            cB_IPs.Items.Add("127.0.0.1");
            cB_IPs.Items.Add("192.168.110.96");
            cB_IPs.SelectedIndex = 0;//默认选中0个对象
        }

        /// <summary>
        /// 打开服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button2_Click(object sender, EventArgs e)
        {
            //1.初始化
            socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
            //2.监听
            IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse(cB_IPs.Text) ,(int)numericUpDown1.Value);
            try
            {
                socket.Bind(iPEndPoint);//监听
                socket.Listen(10);//一秒可以监听多少个客户端连接
                MessageBox.Show("服务器打开成功");
                connectingFlag = true;
                #region 监视客户端
                //监听客户端
                ThreadPool.QueueUserWorkItem((Object o) =>
                {
                   
                    while (true)
                    {
                        //判断服务器是否连接
                        if (!connectingFlag)
                        {
                            break;
                        }
                        Socket socket1 = socket.Accept();//客户端连接
                        sockets.Add(socket1);
                        //获取客户端连接IP和端口
                        IPEndPoint iPEndPoint1 = (IPEndPoint)socket1.RemoteEndPoint;
                        //显示到数据表格
                        dataGridView1.Invoke(new Action(() =>
                        {
                            dataGridView1.Rows.Add(iPEndPoint1.Address, iPEndPoint1.Port);
                        }));
                    }
                    
                });
                #endregion
                #region 监视客户端发送数据
                Task.Run(() =>
                {
                    while (true)
                    {
                        //判断服务器是否连接
                        if (!connectingFlag)
                        {
                            break;
                        }
                        //1.判断是否有客户端
                        if (sockets.Count == 0)
                        {
                            continue;
                        }
                        //2.循环监视客户端
                        for (int i = sockets.Count-1; i >=0; i--)
                        {
                            //3.判断用户是否下线
                            bool downStatus = sockets[i].Poll(1,SelectMode.SelectRead);
                            //true下线
                            if (downStatus)
                            {
                                dataGridView1.Invoke(new Action(() =>
                                {
                                    dataGridView1.Rows.RemoveAt(i);//删除显示
                                }));
                                sockets.RemoveAt(i);//删除客户端
                                continue;
                            }
                            try
                            {
                                //4.接收用户信息
                                byte[] data = new byte[1024];
                                int dataLength = sockets[i].Receive(data);
                                //判断用户是否发送数据
                                if (dataLength > 0)
                                {
                                    //解析用户发送数据
                                    string send = encoding.GetString(data);
                                    //获取发送用户ip和端口
                                    IPEndPoint iPEndPoint1 = (IPEndPoint)sockets[i].RemoteEndPoint;
                                    //显示发送信息
                                    richTextBox2.Invoke(new Action(() =>
                                    {
                                        richTextBox2.AppendText($"{iPEndPoint1.Address} [{DateTime.Now.ToString("HH:mm:ss")}]:{encoding.GetString(data, 0, dataLength)}" + Environment.NewLine);
                                    }));
                                }
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show(ex.Message);
                            }

                        }
                        
                    }
                });
                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show($"服务端开始失败:{ex}");
            }

        }

        /// <summary>
        /// 发送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button3_Click(object sender, EventArgs e)
        {
            try
            {
                //判断是否群发
                int index = dataGridView1.CurrentCell.RowIndex;
                //判断是否群发
                if (checkBox1.Checked)
                {
                    foreach (Socket item in sockets)
                    {
                        item.Send(encoding.GetBytes(richTextBox1.Text));
                    }
                }
                else
                {
                    //获取客户端socket
                    Socket socket = sockets[index];
                    //发送
                    socket.Send(encoding.GetBytes(richTextBox1.Text));
                }
            }
            catch (Exception ex)
            {

                MessageBox.Show($"发送失败:{ex}");
            }
      
        }

        /// <summary>
        /// 断开服务器连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button1_Click(object sender, EventArgs e)
        {
            if (connectingFlag)
            {
                connectingFlag = false;
                sockets.Clear();//清除集合
                dataGridView1.Rows.Clear();//清除显示
                socket.Close();//关闭服务器
            }
        }
    }
}

 

posted @ 2024-07-26 17:51  别动我的猫  阅读(1052)  评论(0编辑  收藏  举报