• [转贴]基于UDP、TCP协议的C#网络编程之一


    转自新浪"烈·翼·焚·天"的博客,原文地址:http://blog.sina.com.cn/s/blog_4c459776010009bp.html

      写这篇之前,先简单介绍一下TCP、UDP协议,深的讲不出来,有不明白的请问我秘书Dawnh同学。

        TCP(传输控制协议)是 TCP/IP 协议栈中的传输层协议,它通过序列确认以及包重发机制,提供可靠的数据流发送和到应用程序的虚拟连接服务。与IP协议相结合, TCP组成了因特网协议的核心。
        UDP(用户数据报协议)是ISO参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。 UDP协议基本上是 IP 协议与上层协议的接口。UDP协议适用端口分辨运行在同一台设备上的多个应用程序。
        C#中,已将TCP,UDP,SMTP等协议封装为相应的类型库,提供了一系列方法供程序员进行操作,可以简单的理解为,基于TCP的编程就好象通电话,我拨打贱人甲电话,贱人甲必须按下接听键,我们之间才能建立起有效的连接,而基于UDP的编程就好象是收音机广播,我这头只管播,对面谁在听或者是不是收到我并不关心。TCP、UDP同属于高层协议,复杂程度是大大不如Socket编程的。
        下面我准备写两个例子,一个用UDP,一个用TCP,TCP比较好理解,UDP实际上也不麻烦,但是从网上找资料看你会看的非常晕,MSDN的各种Sample也统统放到一个类里写,效果并不好,我稍微一总结,先写个基于UDP的例子。
        示例一:UDP
        窗体:
       
       
        Form1做为服务器端,按下Send,将文本框的值发送出去,Form1做为客户端,接收信息并加入到ListBox控件中。
           Form1:

    public partial class Form1 : Form
        {
            UdpClient uc; //声明UDPClient
            public Form1()
                     
                uc = new UdpClient(); //初始化
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
                     
                string temp = this.textBox1.Text; //保存TextBox文本

                //将该文本转化为字节数组
                byte[] b = System.Text.Encoding.UTF8.GetBytes(temp);

                //向本机的8888端口发送数据
                uc.Send(b, b.Length,Dns.GetHostName(),8888);
            }
        }

           Form2:

    public partial class Form2 : Form
        {
            UdpClient uc = null; //声明UDPClient
            public Form1()
            {

                //屏蔽跨线程改控件属性那个异常
                CheckForIllegalCrossThreadCalls = false;
                InitializeComponent();

                //注意此处端口号要与发送方相同
                uc = new UdpClient(8888);

                //开一线程
                Thread th = new Thread(new ThreadStart(listen));

                //设置为后台
                th.IsBackground = true;
                th.Start();
            }
            private void listen()
            {

                //声明终结点
                IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.0.10"),8888);
                while (true)
                {

                    //获得Form1发送过来的数据包
                    string text = System.Text.Encoding.UTF8.GetString(uc.Receive(ref iep));

                    //加入ListBox
                    this.listBox1.Items.Add(text);
                }
            }
        }

        需要注意的地方非常之多,别看就这么几行,先看Form1中的UdpClient声明,这里使用了无参的构造函数uc = new UdpClient(); 我们写基于TCP的程序可以知道,TcpClient声明同时直接指出其端口是很方便的,也是必然的,不指定端口你上哪收数据去?因为UDP是一种无连接的传输层协议,想给谁发就给谁发,所以如果我们这么声明了UdpClient,但是接收方如果想收到数据包,就必须建立基于发送方发送数据端口的UdpClient(见Form2),这么说有点乱,接着往下看。当我们声明了uc = new UdpClient(); 那下面的写法就相对固定了,在Send数据的时候,需要指明其目标计算机,以及将要发送的端口,例如示例中的uc.Send(b, b.Length,Dns.GetHostName(),8888);Send有很多重载的方法,如果你想这么写uc.Send(b, b.Length);那就必须在Send之前在UdpClient与目标计算机之间做一下连接,否则无法发送,我们可以这么写:
    uc = new UdpClient(); 
    uc.Connect(IPAddress.Parse("192.168.0.10"), 8888);
    .....
    uc.Send(b, b.Length);
         这里注意,IP地址跟端口号可以随便写,只要对方监听着你的这个端口,说监听有点小错,UDP并不需要监听,姑且这么说,形象一点。
         另外,很多人遇到这么个问题,无论在TCP还是UDP中,很多时候因为编码问题,接收到以字节数组发送的中文消息,还原后出现乱码,这个问题的解决办法是发送方与接收方都使用同一种Encoding,发送方用UTF-8.GetBytes,接收方也同样使用UTF-8.GetString这个方法便可传递中文,网上鸟多,墨迹半天也解决不了,汗个。
         再来看Form2,与Form1相反,在Form2中实例化UdpClient时,需要指明其端口,因为我们要捕获发送过来的消息,注意这两句话:

    IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.0.10"),8888);

    .........
    string text = System.Text.Encoding.UTF8.GetString(uc.Receive(ref iep));

         网上对这个貌似还是有点误解,很多人说,这里的IPEndPoint的端口号如果随便指定,也可以收到发送过来的消息,但是就是不知道为什么,我写的更简单:

        

    IPEndPoint iep = null;

    .........
    string text = System.Text.Encoding.UTF8.GetString(uc.Receive(ref iep));

         看出问题来了吧,关键是uc.Receive方法里的ref参数,ref关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。所以你只要扔给它一个值就得了,管他什么端口号,况且端口早在声明UdpClient的时候就指定好了。

         有点长,分两截。

    yjmyzz: https://cid-2959920b8267aaca.skydrive.live.com/self.aspx/WPF/UDP^_WPF^_Demo.rar wpf版的udp小示例

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    四十五、android camera
    MyEclipse优化技巧
    设置MyEclipse编码、补全快捷键、字体大小
    妈妈走开一会儿
    四十一、Android Notification通知详解
    四十三、设置Activity永不过期,即不执行onDestroy()
    七、oracle 表查询二
    四十七、实现调用Android手机的拍照功能
    四十四、Android之android:layout_weight详解
    一、oracle 高水位线详解
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1688928.html
Copyright © 2020-2023  润新知