c#用Socket实现服务端与客户端通信实例(同步)

c#用Socket实现服务端与客户端通信实例(同步)

编码文章call10242025-02-01 3:11:1211A+A-

因为手里有好几个东西要做,每天只能抽出一部分时间来弄同一个,所以昨天我看了一下得到本机IP,就被迫去干别的了,今天来实现把这个IP发送到服务端。


实现这个事,一个是同步,一个是异步,各有各的特点吧,今天先说一下如何同步实现

先来看运行结果,点击按钮,将IP发送给老师,报告学生上线:


1、新建项目Student,用来做发送端,代码如下:

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

namespace Student
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //得到本机IP
            textBox1.Text = GetMyIP();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            string IPstr = textBox1.Text;

            TcpClient c = new TcpClient();
            //建立连接,IP与端口,端口只要没有其它软件占用就可以
            c.Connect(IPAddress.Parse("127.0.0.1"), 7878);
            
            if (c.Connected)
            {
                byte[] bytes = Encoding.UTF8.GetBytes(IPstr);
                NetworkStream s = c.GetStream();
                s.Write(bytes, 0, bytes.Length);
                s.Close();
                c.Close();
            }
            else
            {
                MessageBox.Show("与目标机器连接失败!");
            }
        }

        /// 
        /// 得到本机IP
        /// 
        /// 
        public string GetMyIP()
        {
            try
            {
                string computername = Dns.GetHostName();
                IPHostEntry ipall = Dns.GetHostEntry(computername);
                for (int i = 0; i < ipall.AddressList.Length; i++)
                {
                    string theip = ipall.AddressList[i].ToString();
                    if (theip.LastIndexOf(".") != -1)
                    {
                        return theip;
                    }
                }
                return "未得到IP地址";
            }
            catch (Exception ErrMsg)
            {
                return ErrMsg.ToString();
            }
        }
    }
}

2、新建一个Teacher项目,用来做接收端,界面就放一个Label1就好,代码如下:

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

namespace Teacher
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //线程
        Thread getclientinfo = null;
        //TPC连接对像
        TcpListener TheClient = null;

        private void Form1_Load(object sender, EventArgs e)
        {
            //此操作需要要线程中进行
            getclientinfo = new Thread(new ThreadStart(getclient));
            getclientinfo.Start();
        }

        //得客发送端消息的方法
        private void getclient()
        {
            TheClient = new TcpListener(new IPEndPoint(IPAddress.Any, 7878));
            try
            {
                TheClient.Start();

                while (true)
                {
                    try
                    {
                        TcpClient client = TheClient.AcceptTcpClient();
                        //尝试获取数据流
                        NetworkStream stream = client.GetStream();

                        if (stream.CanRead)
                        {
                            string ipStr = "";
                            byte[] bytes = new byte[1024];

                            //数据流长度
                            int i = stream.Read(bytes, 0, bytes.Length);
                            //读到字符串中
                            ipStr = Encoding.UTF8.GetString(bytes, 0, i);

                            //委托更改控件值,因为在线程中,直接更改会报错
                            this.Invoke(new Action(
                                () =>
                                {
                                    label1.Text = ipStr + "同学上线了!";
                                    //加这句是为了调试同步效果,我暂时注释掉
                                    MessageBox.Show(ipStr);
                                }));
                        }
                        client.Close();
                    }
                    //这里可以根据错误原因自己判断
                    //当关闭窗体时也会引发,如果是这个原因就什么也不做就行
                    catch
                    {
                        //出错时的操作,否则进程不会退出
                        TheClient.Stop();
                        getclientinfo.Abort();
                    }
                }
            }
            finally
            {
                TheClient.Stop();
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            //关闭窗时的操作,否则进程不会退出
            TheClient.Stop();
            getclientinfo.Abort();
        }
    }
}

3、代码已经结束了。下来说一下同步传输的特点

//MessageBox.Show(ipStr); //可以加一个对话框看下效果

接收端如果加上了这个对话框代码,接收端弹出对话框以后,如果你不关掉它,程序会是阻塞状态,你必须关闭对话框,才能继续。如下图:

总结:需要注意的主要有3点

1、是在线程中更改控件值需要用委托,

this.Invoke(new Action()

如果用action用不太好,可以用delegate,比较简单,如果不更改控件不需要用委托

2、接收端要做关闭线程和连接对象处理,否则关闭窗体后,进程不会退出

3、因为是同步,如果一个true循环没有结束,就会阻塞

明天再来说说异步的处理方式。

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4