【筆記】組播的使用


  UDP相對於TCP來說,雖然是無連接,不可靠傳輸,但是可以實現組播,可以同時給多個主機發送數據,比如聊天室之類的應用,如果為每個用戶之間都建立一個Tcp連接,而且每次發送的數據又是相同的,這樣做使得程序開銷大,而且占用內存多,Udp還有一個廣播的服務,但是廣播不能篩選,也就是說廣播會向所有在同一子網的主機發送數據,這樣無疑也增加了網絡負擔,這時就可以通過Udp的組播來實現,最近一直在摸索中,下面對做一下組播的總解

  組播的地址采用D類IP地址,范圍是從 224.0.0.0239.255.255.255,下面有幾個保留地址,一般不作為用戶使用的地址

    224.0.0.1 - 該子網上的所有主機。

    224.0.0.2 - 該子網上的所有路由器。

    224.0.0.5 - 開放最短路徑優先(Open Shortest Path First,OSPF)算法第2版,設計用於到達某個網絡上的所有OSPF路由器。

    224.0.0.6 - 開放最短路徑優先算法第2版,設計用於到達某個網絡上的所有OSPF指定的路由器。

    224.0.0.9 - 路由信息協議(Routing Information Protocol,RIP)第2版。

    224.0.1.1 - 網絡時間協議(Network Time Protocol)。

    過多詳細介紹見百度百科  http://baike.baidu.com/view/1871353.htm

  對組播的使用:創建套接字,綁定本地地址,加入組播,監聽組播信息

1、首先定義一個套接字狀態信息,用於異步時保存信息

        public class StateObject
        {
            public Socket sock;
            public byte[] buffer = new byte[1024];
            public EndPoint endpoint;
            public StateObject(Socket sock, EndPoint endpoint)
            {
                this.sock = sock;
                this.endpoint = endpoint;
            }
        }

2、創建套接字,綁定本地地址,加入組播,監聽組播信息

        private static IPAddress mcastAddress;
        private static int mcastPort;
        private static Socket mcastSocket; 
        private static MulticastOption mcastOption;

        private void btnJoin_Click(object sender, EventArgs e)
        {
            //組播地址和端口
            mcastAddress = IPAddress.Parse("224.168.100.2");
            mcastPort = 8000;
            try
            {
                //組播套接字,綁定本地地址(組播端口)
                mcastSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(tbLocalIP.Text), mcastPort);
                mcastSocket.Bind(localEP);

                //加入組播
                mcastOption = new MulticastOption(mcastAddress, IPAddress.Parse(tbLocalIP.Text));
                mcastSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption);

                //開始接收信息
                byte[] bytes = new Byte[1024];
                EndPoint remoteEP = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
                StateObject so = new StateObject(mcastSocket, remoteEP);
                mcastSocket.BeginReceiveFrom(so.buffer, 0, so.buffer.Length, SocketFlags.None, ref so.endpoint, ReceiveFromCallback, so);
            }
            catch (Exception) 
            {
            }
        }
        private void ReceiveFromCallback(IAsyncResult ar)
        {
            StateObject so = ar.AsyncState as StateObject;
            try
            {
                int length = so.sock.EndReceiveFrom(ar, ref so.endpoint);
                string recvstr = System.Text.Encoding.UTF8.GetString(so.buffer, 0, length);
                MessageBox.Show(recvstr);
                //繼續接收消息
                so.sock.BeginReceiveFrom(so.buffer, 0, so.buffer.Length, SocketFlags.None, ref so.endpoint, ReceiveFromCallback, so);
            }
            catch (SocketException)
            {
                //連接斷開
            }
            catch (ObjectDisposedException)
            {
                //套接字關閉
            }
        }

3、向組播發送信息,只要加入了該多播組的成員都能收到該信息

        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            try
            {
                IPEndPoint endPoint = new IPEndPoint(mcastAddress, mcastPort);
                mcastSocket.SendTo(System.Text.Encoding.UTF8.GetBytes("你好"), endPoint);
            }
            catch (SocketException)
            {
                //連接斷開
            }
            catch (ObjectDisposedException)
            {
                //套接字關閉
            }
        }

 4、最后說下套接字屬性的設置問題,也就是SetSocketOption函數

  該函數有四個重載,分別設置不同屬性,具體屬性定義在MSDN上有

     http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.setsocketoption(v=VS.80).aspx    

    Socket.SetSocketOption (SocketOptionLevel, SocketOptionName, Boolean) 將指定的 Socket 選項設置為指定的 Boolean 值。
    Socket.SetSocketOption (SocketOptionLevel, SocketOptionName, Byte[]) 將指定的 Socket 選項設置為指定的值,表示為字節數組。
    Socket.SetSocketOption (SocketOptionLevel, SocketOptionName, Int32) 將指定的 Socket 選項設置為指定的整數值。
    Socket.SetSocketOption (SocketOptionLevel, SocketOptionName, Object) 將指定的 Socket 選項設置為指定值,表示為對象。

具體屬性說明,具體屬性對於的SocketOptionLevel可以查看上面地址,不同的函數對於的設置又不一樣

http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socketoptionname(v=vs.80).aspx

  成員名稱 說明
由 .NET Compact Framework 支持 AcceptConnection 套接字正在偵聽。 
由 .NET Compact Framework 支持 AddMembership 添加一個 IP 組成員。 
由 .NET Compact Framework 支持 AddSourceMembership 聯接源組。 
由 .NET Compact Framework 支持 BlockSource 阻止源中的數據。 
由 .NET Compact Framework 支持 Broadcast 允許在套接字上發送廣播消息。 
由 .NET Compact Framework 支持 BsdUrgent 使用 RFC-1222 中定義的緊急數據。此選項只能設置一次,而且設置以后就不能關閉。 
由 .NET Compact Framework 支持 ChecksumCoverage 設置或獲取 UDP 校驗和覆蓋。 
由 .NET Compact Framework 支持 Debug 記錄調試信息。 
由 .NET Compact Framework 支持 DontFragment 不對 IP 數據報進行分段。 
由 .NET Compact Framework 支持 DontLinger 完全關閉套接字,不做逗留。 
由 .NET Compact Framework 支持 DontRoute 不路由,將數據包直接發送到接口地址。 
由 .NET Compact Framework 支持 DropMembership 放置一個 IP 組成員。 
由 .NET Compact Framework 支持 DropSourceMembership 放置一個源組。 
由 .NET Compact Framework 支持 Error 獲取錯誤狀態並清除。 
由 .NET Compact Framework 支持 ExclusiveAddressUse 使套接字能夠為獨占訪問進行綁定。 
由 .NET Compact Framework 支持 Expedited 使用 RFC-1222 中定義的加急數據。此選項只能設置一次,而且設置以后就無法關閉。 
由 .NET Compact Framework 支持 HeaderIncluded 指示應用程序為輸出數據報提供 IP 頭。 
  HopLimit 指定 Internet 協議版本 6 (IPv6) 數據包的最大路由器躍點數目。這類似於 Internet 協議版本 4 的生存時間 (TTL)。 
由 .NET Compact Framework 支持 IPOptions 指定要插入到輸出數據報中的 IP 選項。 
由 .NET Compact Framework 支持 IpTimeToLive 設置 IP 頭生存時間字段。 
由 .NET Compact Framework 支持 KeepAlive 使用 keep-alive。 
由 .NET Compact Framework 支持 Linger 如果存在未發送的數據,則在關閉時逗留。 
由 .NET Compact Framework 支持 MaxConnections 不受支持;如果使用,將引發 SocketException。 
由 .NET Compact Framework 支持 MulticastInterface 為輸出的多路廣播數據包設置接口。 
由 .NET Compact Framework 支持 MulticastLoopback IP 多路廣播環回。 
由 .NET Compact Framework 支持 MulticastTimeToLive IP 多路廣播生存時間。 
由 .NET Compact Framework 支持 NoChecksum 發送校驗和設置為零的 UDP 數據報。 
由 .NET Compact Framework 支持 NoDelay 為發送合並禁用 Nagle 算法。 
由 .NET Compact Framework 支持 OutOfBandInline 接收正常數據流中的帶外數據。 
由 .NET Compact Framework 支持 PacketInformation 返回有關接收到的數據包的信息。 
由 .NET Compact Framework 支持 ReceiveBuffer 指定為接收保留的每個套接字緩沖區空間的總量。這與最大消息大小或 TCP 窗口的大小無關。 
由 .NET Compact Framework 支持 ReceiveLowWater 為 Receive 操作指定低水印。 
由 .NET Compact Framework 支持 ReceiveTimeout 接收超時。此選項只適用於同步方法,它對異步方法(如 BeginSend 方法)無效。 
由 .NET Compact Framework 支持 ReuseAddress 允許將套接字綁定到已在使用中的地址。 
由 .NET Compact Framework 支持 SendBuffer 指定為發送保留的每個套接字緩沖區空間的總量。這與最大消息大小或 TCP 窗口的大小無關。 
由 .NET Compact Framework 支持 SendLowWater 為 Send 操作指定低水印。 
由 .NET Compact Framework 支持 SendTimeout 發送超時。此選項只適用於同步方法,它對異步方法(如 BeginSend 方法)無效。 
由 .NET Compact Framework 支持 Type 獲取套接字類型。 
由 .NET Compact Framework 支持 TypeOfService 更改服務字段的 IP 頭類型。 
由 .NET Compact Framework 支持 UnblockSource 取消阻止先前被阻止的源。 
  UpdateAcceptContext 使用現有套接字的屬性更新已接受套接字的屬性。這等效於使用 Winsock2 SO_UPDATE_ACCEPT_CONTEXT 套接字選項,並且僅在面向連接的套接字上受支持。 
  UpdateConnectContext 使用現有套接字的屬性更新已連接套接字的屬性。這等效於使用 Winsock2 SO_UPDATE_CONNECT_CONTEXT 套接字選項,並且僅在面向連接的套接字上受支持。 
由 .NET Compact Framework 支持 UseLoopback 可能時避開硬件。 
 

 

例如在使用Udp廣播數據的時候,需要設置Broadcast屬性為true

  在函數 Socket.SetSocketOption (SocketOptionLevel, SocketOptionName, Boolean)

    Broadcast屬性對應的 SocketOptionLevelSocket

  則調用為

    sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM