WPF-TCP(Socket)通讯

时间:2025-04-18 08:03:11

 1.界面XAML代码:

<StackPanel>

        <Canvas Margin="10,20" Height="30">

            <Label Content="IP:" Height="30" Width="30"  FontSize="18" HorizontalContentAlignment="Center" ="8"/>

            <TextBox x:Name="txtIp" Text="192.168.249.239" Height="30" Width="150" FontSize="20" HorizontalContentAlignment="Center" ="41" />

            <Label Content="Port:" Height="30" Width="50" FontSize="18" HorizontalContentAlignment="Center" ="210"/>

            <TextBox x:Name="txtPort" Text="45000"  Height="30" Width="150" FontSize="20" HorizontalContentAlignment="Center" ="263"  />

            <Button x:Name="btnStartServer" Content="接服务段" Height="30" Width="100" ="460"/>

        </Canvas>

        <TextBox Name="txtLog" Height="300" AcceptsReturn="True" TextWrapping="Wrap"></TextBox>

        <Canvas Margin="0,20" Height="30">

            <TextBox x:Name="txtMsg" Height="30" Width="450" FontSize="20" HorizontalContentAlignment="Center" ="0" />

            <Button x:Name="btnSendMsg" Content="发送消息" Height="30" Width="100" ="470" />

        </Canvas>

    </StackPanel>

2.后台代码:

   using System;

using ;

using ;

using ;

using ;

using ;

 

namespace WPF_Client

{

    /// <summary>

    ///  的交互逻辑

    /// </summary>

    public partial class MainWindow : Window

    {

        private Socket _socket;

        public MainWindow()

        {

            InitializeComponent();

 

             += BtnSendMsg_Click;//注册事件

             += BtnConnect_Click;

            Closing += ClientWindows_Closing;

        }

 

        /// <summary>

        /// 窗口关闭事件

        /// </summary>

        private void ClientWindows_Closing(object sender, e)

        {

            ServerExit(null, _socket);//向服务端说我下线了。

        }

 

        /// <summary

        /// 连接按钮事件

        /// </summary>

        private void BtnConnect_Click(object sender, RoutedEventArgs e)

        {

            //1、创建Socket对象

            Socket socket = new Socket(, , );

            _socket = socket;

            //2、连接服务器,绑定IP 与 端口

            IPEndPoint iPEndPoint = new IPEndPoint((), int.Parse());

            try

            {

                (iPEndPoint);

                ("连接成功!", "提示");

            }

            catch (Exception)

            {

                ("连接失败,请重新连接!", "提示");

                return;

            }

            //3、接收消息

            (new WaitCallback(ReceiveServerMsg), socket);

        }

 

        /// <summary>

        /// 不断接收客户端信息子线程方法

        /// </summary>

        /// <param name="obj">参数Socke对象</param>

        private void ReceiveServerMsg(object obj)

        {

            var proxSocket = obj as Socket;

            //创建缓存内存,存储接收的信息   ,不能放到while中,这块内存可以循环利用

            byte[] data = new byte[1020 * 1024];

            while (true)

            {

                int len;

                try

                {

                    //接收消息,返回字节长度

                    len = (data, 0, , );

                }

                catch (Exception ex)

                {

                    //7、关闭Socket

                    //异常退出

                    try

                    {

                        ServerExit(string.Format("服务端:{0}非正常退出", ()), proxSocket);

                    }

                    catch (Exception)

                    {

 

                    }

                    return;//让方法结束,终结当前客户端数据的异步线程,方法退出,即线程结束

                }

 

                if (len <= 0)//判断接收的字节数

                {

                    //7、关闭Socket

                    //小于0表示正常退出

                    try

                    {

                        ServerExit(string.Format("服务端:{0}正常退出", ()), proxSocket);

                    }

                    catch (Exception)

                    {

 

                    }

                    return;//让方法结束,终结当前客户端数据的异步线程,方法退出,即线程结束

                }

                //将消息显示到TxtLog

                string msgStr = (data, 0, len);

                //拼接字符串

                AppendTxtLogText(string.Format("接收到服务端:{0}的消息:{1}", (), msgStr));

            }

        }

 

        /// <summary>

        /// 客户端退出调用

        /// </summary>

        /// <param name="msg"></param>

        private void ServerExit(string msg, Socket proxSocket)

        {

            AppendTxtLogText(msg);

            try

            {

                if ()//如果是连接状态

                {

                    ();//关闭连接

                    (100);//100秒超时间

                }

            }

            catch (Exception ex)

            {

            }

        }

 

        /// <summary>

        /// 发送信息按钮事件

        /// </summary>

        private void BtnSendMsg_Click(object sender, RoutedEventArgs e)

        {

            byte[] data = (this.);

            //6、发送消息

            _socket.Send(data, 0, , ); //指定套接字的发送行为

            this. = null;

        }

 

        /// <summary>

        /// 向文本框中追加信息

        /// </summary>

        /// <param name="str"></param>

        private void AppendTxtLogText(string str)

        {

            if (!(()))//判断跨线程访问

            {

                

                //异步方法

                this.(new Action<string>(s =>

                {

                    this. = string.Format("{0}\r\n{1}", s, );

                }), str);

            }

            else

            {

                this. = string.Format("{0}\r\n{1}", str, );

            }

        }

    }

}

 

 

  1. 首先在类里面声明一个byte数组(static byte[] b=new  byte[1024];),用来存放客户端发送来的数据,数组的大小可以根据自己的需求填写,然后就写你本电脑的IP地址(获取电脑的IP地址方法:window键+R键,然后输入CMD回车键,再输入ipconfig,按回车键,找到IPv4地址,右边的就是你电脑的ip地址),也可以用自动获取本机的ip地址的方法;然后就指定一个端口(注意设置的端口不能和电脑里的其它端口相同,还要设置你写的端口允许通过防火墙或者关闭防火墙都可以),然后就声明Socket对象,详细代码如上。

执行效果图

 

 

3.服务端的界面代码如下:

<StackPanel>

        <Canvas Margin="10,20" Height="30">

            <Label Content="IP:" Height="30" Width="30"  FontSize="18" HorizontalContentAlignment="Center" ="8"/>

            <TextBox x:Name="txtIp" Height="30" Width="150" FontSize="20" HorizontalContentAlignment="Center" ="41" />

            <Label Content="Port:" Height="30" Width="50" FontSize="18" HorizontalContentAlignment="Center" ="210"/>

            <TextBox x:Name="txtPort" Text="45000"  Height="30" Width="150" FontSize="20" HorizontalContentAlignment="Center" ="263"  />

            <Button x:Name="btnStartServer" Content="开启服务" Height="30" Width="100" ="460"/>

        </Canvas>

        <TextBox Name="txtLog" Height="300" AcceptsReturn="True" TextWrapping="Wrap"></TextBox>

        <Canvas Margin="0,20" Height="30">

        <TextBox x:Name="txtMsg" Height="30" Width="450" FontSize="20" HorizontalContentAlignment="Center" ="0" />

        <Button x:Name="btnSendMsg" Content="发送消息" Height="30" Width="100" ="470" />

        </Canvas>

    </StackPanel>

 

4.后台代码如下:

using System;

using ;

using ;

using ;

using ;

using ;

using ;

 

namespace WPF_Sever

{

    /// <summary>

    ///  的交互逻辑

    /// </summary>

    public partial class MainWindow : Window

    {

        List<Socket> clientScoketLis = new List<Socket>();//存储连接服务器端的客户端的Socket

        public MainWindow()

        {

            InitializeComponent();

 

             += BtnStartServer_Click;//事件注册

             += BtnSendMsg_Click;

            Closing += MainWindow_Closing;

        }

        

        /// <summary>

        /// 关闭事件

        /// </summary>

        private void MainWindow_Closing(object sender, e)

        {

            //改成for循环即可

            for (int i = 0; i < ; i++)//向每个客户端说我下线了

            {

                ClientExit(null, clientScoketLis[i]);

            }

        }

 

        /// <summary>

        /// 开启服务事件

        /// </summary>

        private void BtnStartServer_Click(object sender, RoutedEventArgs e)

        {

            //1、创建Socket对象

            //参数:寻址方式,当前为Ivp4  指定套接字类型   指定传输协议Tcp;

            Socket socket = new Socket(, , );

            //2、绑定端口、IP

            IPEndPoint iPEndPoint = new IPEndPoint((GetCurrentLoginIP()), int.Parse());

            (iPEndPoint);

            //3、开启侦听   10为队列最多接收的数量

            (100);//如果同时来了100个连接请求,只能处理一个,队列中10个在等待连接的客户端,其他的则返回错误消息。

            //4、开始接受客户端的连接  ,连接会阻塞主线程,故使用线程池。

            (new WaitCallback(AcceptClientConnect), socket);

        }

        /// <summary>

        /// 获取本地的IP地址

        /// </summary>

        /// <returns></returns>

        private string GetCurrentLoginIP()

        {

            ///获取本地的IP地址

            string ThisloginIP = string.Empty;

            foreach (IPAddress _IPAddress in (()).AddressList)

            {

                if (_IPAddress.() == "InterNetwork")

                {

                    ThisloginIP = _IPAddress.ToString();

                }

            }

             = ThisloginIP;

            return ThisloginIP;

        }

 

        /// <summary>

        /// 线程池线程执行的接受客户端连接方法

        /// </summary>

        /// <param name="obj">传入的Socket</param>

        private void AcceptClientConnect(object obj)

        {

            //转换Socket

            var serverSocket = obj as Socket;

 

            AppendTxtLogText("服务端开始接收客户端连接!");

 

            //不断接受客户端的连接

            while (true)

            {

                //5、创建一个负责通信的Socket

                Socket proxSocket = ();

                AppendTxtLogText(string.Format("客户端:{0}连接上了!", ()));

                //将连接的Socket存入集合

                (proxSocket);

                //6、不断接收客户端发送来的消息

                (new WaitCallback(ReceiveClientMsg), proxSocket);

            }

        }

        /// <summary>

        /// 不断接收客户端信息子线程方法

        /// </summary>

        /// <param name="obj">参数Socke对象</param>

        private void ReceiveClientMsg(object obj)

        {

            var proxSocket = obj as Socket;

            //创建缓存内存,存储接收的信息   ,不能放到while中,这块内存可以循环利用

            byte[] data = new byte[1020 * 1024];

            while (true)

            {

                int len;

                try

                {

                    //接收消息,返回字节长度

                    len = (data, 0, , );

 

                   

                }

                catch (Exception ex)

                {

                    //7、关闭Socket

                    //异常退出

                    try

                    {

                        ClientExit(string.Format("客户端:{0}非正常退出", ()), proxSocket);

                    }

                    catch (Exception)

                    {

                    }

                    return;//让方法结束,终结当前客户端数据的异步线程,方法退出,即线程结束

                }

 

                if (len <= 0)//判断接收的字节数

                {

                    //7、关闭Socket

                    //小于0表示正常退出

                    try

                    {

                        ClientExit(string.Format("客户端:{0}正常退出", ()), proxSocket);

                    }

                    catch (Exception)

                    {

                    }

                    return;//让方法结束,终结当前客户端数据的异步线程,方法退出,即线程结束

                }

                //将消息显示到TxtLog

                string msgStr = (data, 0, len);

                //拼接字符串

                AppendTxtLogText(string.Format("接收到客户端:{0}的消息:{1}", (), msgStr));

            }

        }

 

        /// <summary>

        /// 消息发送事件

        /// </summary>

        private void BtnSendMsg_Click(object sender, RoutedEventArgs e)

        {

            foreach (Socket proxSocket in clientScoketLis)

            {

                if ()//判断客户端是否还在连接

                {

                    byte[] data = (this.);

                    //6、发送消息

                    (data, 0, , ); //指定套接字的发送行为

                    this. = null;

                }

            }

        }

        /// <summary>

        /// 向文本框中追加信息

        /// </summary>

        /// <param name="str"></param>

        private void AppendTxtLogText(string str)

        {

            if (!(()))//判断跨线程访问

            {

                //异步方法

                this.(new Action<string>(s =>

                {

                    this. = string.Format("{0}\r\n{1}", s, );

                }), str);

            }

            else

            {

                this. = string.Format("{0}\r\n{1}", str, );

            }

        }

        /// <summary>

        /// 客户端退出调用

        /// </summary>

        /// <param name="msg"></param>

        private void ClientExit(string msg, Socket proxSocket)

        {

            AppendTxtLogText(msg);

            (proxSocket);//移除集合中的连接Socket

 

            try

            {

                if ()//如果是连接状态

                {

                    ();//关闭连接

                    (100);//100秒超时间

                }

            }

            catch (Exception ex)

            {

            }

        }

    }

}

运行效果