zoukankan      html  css  js  c++  java
  • C# Socket UDP 案例

    UDP的简单应用:
             由于UDP是一种无连接的协议。因此,为了使服务器应用能够发送和接收UDP数据包,则需要做两件事情:
             创建一个Socket对象;
             将创建的套接字对象与本地IPEndPoint进行绑定。
             完成上述步骤后,那么创建的套接字就能够在IPEndPoint上接收流入的UDP数据包,或者将流出的UDP数据包发送到网络中任意其他设备商。使用UDP进行通信时,不需要TCP连接。因为异地的主机之间没有建立连接,所以UDP不能使用标准的Send()和Receive()t套接字方法,而是使用两个其他的方法:SendTo()和ReceiveFrom()。
            SendTo()方法指定要发送的数据,和目标机器的IPEndPoint。该方法有多种不同的使用方法,可以根据具体的应用进行选择,但是至少要指定数据包和目标机器。如下:
            SendTo(byte[] data,EndPoint Remote)
            ReceiveFrom()方法同SendTo()方法类似,但是使用EndPoint对象声明的方式不一样。利用ref修饰,传递的不是一个EndPoint对象,而是将参数传递给一个EndPoint对象。

    服务器端:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;

    namespace UDPServer
    {
    class Program
    {
    static void Main(string[] args)
    {
    int recv;
    byte[] data = new byte[1024];

    //构建UDP服务器

    //得到本机IP,设置UDP端口号
    IPEndPoint ipep = new IPEndPoint(IPAddress.Any , 8001);
    Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram , ProtocolType.Udp);

    //绑定网络地址
    newsock.Bind(ipep);

    Console.WriteLine("This is a Server, host name is {0}",Dns.GetHostName());

    //等待客户机连接
    Console.WriteLine("Waiting for a client");

    //得到客户机IP
    IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
    EndPoint Remote = (EndPoint)(sender);
    recv = newsock.ReceiveFrom(data, ref Remote);
    Console .WriteLine ("Message received from {0}: ", Remote.ToString ());
    Console .WriteLine (Encoding .ASCII .GetString (data ,0,recv ));

    //客户机连接成功后,发送欢迎信息
    string welcome = "Welcome ! ";

    //字符串与字节数组相互转换
    data = Encoding .ASCII .GetBytes (welcome );

    //发送信息
    newsock .SendTo (data ,data.Length ,SocketFlags .None ,Remote );
    while (true )
    {
    data =new byte [1024];
    //发送接受信息
    recv =newsock.ReceiveFrom(data ,ref Remote);
    Console .WriteLine (Encoding .ASCII .GetString (data ,0,recv));
    newsock .SendTo (data ,recv ,SocketFlags .None ,Remote );
    }
    }

    }
    }

    客户端:

    (UDP客户机程序与服务器程序非常类似。 因为客户机不需要在指定的UDP端口等待流入的数据,因此,不使用Bind()方法,而是使用在数据发送时系统随机指定的一个UDP端口,而且使用同一个端口接收返回的消息。在看法产品时,要为客户机指定一套UDP端口,以便服务器和客户机程序使用相同的端口号。UDP客户机程序首先定义一个IPEndPoint,UDP服务器将发送数据包到这个IPEndPoint。如果在远程设备上运行UDP服务器程序,在IPEndPoint定义中必须输入适当的IP地址和UDP端口号信息

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;

    namespace UDPClient
    {
    class Program
    {
    static void Main(string[] args)
    {
    byte[] data = new byte[1024];
    string input ,stringData;

    //构建UDP服务器

    Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName());

    //设置服务IP,设置UDP端口号
    IPEndPoint ipep = new IPEndPoint(IPAddress .Parse ("127.0.0.1") , 8001);

    //定义网络类型,数据连接类型和网络协议UDP
    Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

    string welcome = "Hello! ";
    data = Encoding.ASCII.GetBytes(welcome);
    server.SendTo(data, data.Length, SocketFlags.None, ipep);
    IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
    EndPoint Remote = (EndPoint)sender;

    data = new byte[1024];
    //对于不存在的IP地址,加入此行代码后,可以在指定时间内解除阻塞模式限制
    //server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 100);
    int recv = server.ReceiveFrom(data, ref Remote);
    Console.WriteLine("Message received from {0}: ", Remote.ToString());
    Console.WriteLine(Encoding .ASCII .GetString (data,0,recv));
    while (true)
    {
    input = Console .ReadLine ();
    if (input =="exit")
    break ;
    server .SendTo (Encoding .ASCII .GetBytes (input ),Remote );
    data = new byte [1024];
    recv = server.ReceiveFrom(data, ref Remote);
    stringData = Encoding.ASCII.GetString(data, 0, recv);
    Console.WriteLine(stringData);
    }
    Console .WriteLine ("Stopping Client.");
    server .Close ();
    }

    }
    }

    1.问题:在Socket通信中,我们经常要多客户端共用一个端口,但这往往会报错,因为正常来说一个端口只能绑定一次,但释放的时候比较麻烦,所以还是要是实现端口共用的话,就不用执行一个关一个再开一个。

      2.实现端口复用:

         正常绑定:

       

    //定义网络地址,连接类型与网络协议并绑定本地IP与端口
    socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    ipPoint = new IPEndPoint(IPAddress.Parse(ipAdrr), 2012);

    socket.Bind(ipPoint);

       添加共用函数:SetSocketOption

      

    //定义网络地址,连接类型与网络协议并绑定本地IP与端口
    socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    ipPoint = new IPEndPoint(IPAddress.Parse(ipAdrr), 2012);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); //SocketOptionName.ReuseAddress是关键
                socket.Bind(ipPoint); 

    这样就不会报占用同一端口的错了

    对于中断问题:原因大概是因为你关闭socket时,socket.Receive(buffer); 仍出于读取状态。

    改为:

    if (socket.Poll(-1,SelectMode.SelectRead))
    {
    if ( ( dataLength = socket.Receive(buffer) ) > 0)
    {
    Analyer(Encoding.ASCII.GetString(buffer, 0, dataLength));
    }
    }


    以上摘自:一路前行:http://www.cnblogs.com/zhangpengshou/archive/2008/10/09/1307622.html 

          石头:http://rockchao.blog.51cto.com/133022/38849

  • 相关阅读:
    hdu 1032 水题也wrong 两次(于是乎更有刷水题的必要了)
    淘宝刷钻员
    hdu 4006 求第K大的数 优先队列
    骗子满天飞
    hdu 2115 :I Love This Game(Presentation Error容易输出wrong)
    hdu 1048 (map的使用)
    hdu 1722 数论题
    hdu 1237 简单计算器
    Android编码规范
    xamarin开发实例(一) android PC 基于Tcp双向通信
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2361992.html
Copyright © 2011-2022 走看看