Welcome Guest.   Make a donation to an author on the site July 31, 2014, 06:31:06 AM  *

Please login or register.
Or did you miss your validation email?


Login with username and password (forgot your password?)
Why not become a lifetime supporting member of the site with a one-time donation of any amount? Your donation entitles you to a ton of additional benefits, including access to exclusive discounts and downloads, the ability to enter monthly free software drawings, and a single non-expiring license key for all of our programs.


You must sign up here before you can post and access some areas of the site. Registration is totally free and confidential.
 
Your Support Funds this Site: View the Supporter Yearbook.
   
   Forum Home   Thread Marks Chat! Downloads Search Login Register  
Pages: [1]   Go Down
  Reply  |  New Topic  |  Print  
Author Topic: Announcing with UDP in C# - Punching above my weight  (Read 4994 times)
mediaguycouk
Supporting Member
**
Posts: 244


see users location on a map View Profile WWW Give some DonationCredits to this forum member
« on: April 27, 2011, 09:38:33 AM »

Hi all,
I've got a multicast IPTV system where I work and a piece of software, which no longer works in Windows 7, discovers what channels are available using SSDP. I was hoping to write a short console application that would annouce itself and then wait for replies.

My programming skills lend themselves to manipulating online examples to do what I want, but I'm having trouble finding any example code for this type of thing, this being the only example I can find - http://www.codeproject.co...versal.aspx?display=Print . I was wondering if anyone knew of anything else out there?
Logged

Learning C# - Graham Robinson
Renegade
Charter Member
***
Posts: 10,890



Tell me something you don't know...

see users location on a map View Profile WWW Give some DonationCredits to this forum member
« Reply #1 on: April 27, 2011, 10:17:59 AM »

I'm not sure I know what you're asking for.

Are you broadcasting over the LAN or WAN?

I don't know what your requirements are, but my gut is telling me that you'll need to do a significant amount of modifying.
Logged

Slow Down Music - Where I commit thought crimes...

Freedom is the right to be wrong, not the right to do wrong. - John Diefenbaker
mediaguycouk
Supporting Member
**
Posts: 244


see users location on a map View Profile WWW Give some DonationCredits to this forum member
« Reply #2 on: April 27, 2011, 10:37:13 AM »

LAN.

I'm working my way through the example code I linked above and was wondering if anyone else had seen any code like it. I suppose it really was a shot in the dark.

This is the kind of code I'm after

Formatted for C# with the GeSHI Syntax Highlighter [copy or print]
  1. public static bool Discover()
  2.        {
  3.            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  4.            s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
  5.            string req = "M-SEARCH * HTTP/1.1\r\n" +
  6.            "HOST: 239.255.255.250:1900\r\n" +
  7.            "ST:urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n" +
  8.            "MAN:\"ssdp:discover\"\r\n" +
  9.            "MX:3\r\n\r\n";
  10.            byte[] data = Encoding.ASCII.GetBytes(req);
  11.            IPEndPoint ipe = new IPEndPoint(IPAddress.Broadcast, 1900);
  12.            byte[] buffer = new byte[0x1000];
  13.  
  14.            DateTime start = DateTime.Now;
  15.  
  16.            Console.WriteLine("Starting do while < timeout");
  17.            do
  18.            {
  19.                s.SendTo(data, ipe);
  20.                s.SendTo(data, ipe);
  21.                s.SendTo(data, ipe);
  22.  
  23.                int length = 0;
  24.                do
  25.                {
  26.                    length = s.Receive(buffer);
  27.                    string resp = Encoding.ASCII.GetString(buffer, 0, length).ToLower();
  28.                    Console.WriteLine(resp);
  29.                } while (length > 0);
  30.            } while (start.Subtract(DateTime.Now) < _timeout);
  31.            return false;
  32.        }
  33. }
Logged

Learning C# - Graham Robinson
Renegade
Charter Member
***
Posts: 10,890



Tell me something you don't know...

see users location on a map View Profile WWW Give some DonationCredits to this forum member
« Reply #3 on: April 27, 2011, 10:41:46 AM »

Sorry -- I'm a bottle of wine in, and off the top of my head, I'm drawing a blank.

Hopefully someone can chime in with something useful.

Check StackOverFlow. There's usually something there that's a good pointer. Wink I just struck out there with some EXIF issues, but most often they've got an answer. Just follow the links and explore a bit. You likely won't find anything to directly answer the question, but people often point to something that answers it in one way or another.
Logged

Slow Down Music - Where I commit thought crimes...

Freedom is the right to be wrong, not the right to do wrong. - John Diefenbaker
Stoic Joker
Honorary Member
**
Posts: 5,118



View Profile WWW Give some DonationCredits to this forum member
« Reply #4 on: April 27, 2011, 11:59:18 AM »

If you send a packet, and then wait for a response, in the same thread ... Chances are the code will sit there forever waiting for said response.

With TCP you can call select(...) in a loop to see if the socket has become writable/readable and then do X. But if you jump straight to receive, it won't return until its buffer is full ... So if nothing is coming in ... Well...Eternity passes... smiley

UDP is connectionless, so I'm not entirely sure what to use for it. In C/C++ there is recvfrom(...) what if any C# equivalent there is I don't know.

I do know you need to be sure there is something out there listening and waiting to respond, or you'll drive yourself nutz trying to debugg the protocol. I usually keep a packet sniffer running filtered down to just the test packets I'm working with. So I can try to keep track of who dropped what, why, and where.
Logged
Stoic Joker
Honorary Member
**
Posts: 5,118



View Profile WWW Give some DonationCredits to this forum member
« Reply #5 on: April 27, 2011, 12:14:47 PM »

I don't know where I got these originally (it's not my code), which is unfortunate because I've screwed with them a bit. But this is a UDP client server pair written in C++ that does work that might give you some ideas on how to proceed.

* UDP Ping Pong.zip (12.65 KB - downloaded 112 times.)
Logged
mediaguycouk
Supporting Member
**
Posts: 244


see users location on a map View Profile WWW Give some DonationCredits to this forum member
« Reply #6 on: April 27, 2011, 12:52:25 PM »

Thanks Joker
Logged

Learning C# - Graham Robinson
jazper
Coding Snacks Author
Charter Honorary Member
***
Posts: 92



View Profile WWW Give some DonationCredits to this forum member
« Reply #7 on: April 28, 2011, 09:57:05 PM »

I whipped this up real fast, it ain't pretty but should work


[copy or print]
namespace SSDPTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            UdpClient ucs = new UdpClient(12555);

            string data = "M-SEARCH * HTTP/1.1\r\n" +
                            "HOST: 239.255.255.250:1900\r\n" +
                            "ST:upnp:rootdevice\r\n" +
                            "MAN:\"ssdp:discover\"\r\n" +
                            "MX:3\r\n\r\n";
           
            Byte[] sendBytes = Encoding.ASCII.GetBytes(data);
            ucs.Connect("255.255.255.255", 1900);
            ucs.Send(sendBytes, sendBytes.Length);
            ucs.Close();

            IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
            UdpClient ucr = new UdpClient(12555);


            Byte[] receiveBytes = ucr.Receive(ref RemoteIpEndPoint);

            textBox1.Text += Encoding.ASCII.GetString(receiveBytes);

            ucr.Close();

        }
    }
}
Logged
mediaguycouk
Supporting Member
**
Posts: 244


see users location on a map View Profile WWW Give some DonationCredits to this forum member
« Reply #8 on: May 03, 2011, 05:16:44 AM »

Thanks Jazper,
You code confirms what I've previously found. It seems quite easy and reliable to get the router you are connected to to respond to these types of broadcasts but the more unreliable and inconsistent IPTV systems seem to lock up the .Receive commands.

In the end I've been using Wireshark and monitoring the responses of a propriety IPTV multicast program. I then export the filtered Wireshark output into a C# application to get all the channels.

Formatted for C# with the GeSHI Syntax Highlighter [copy or print]
  1. // Please excuse the fact that I found out it was called 'Wireshark' about half way through and then
  2. // couldn't be bothered fixing the function names
  3. private void btnOpenWireShackFile_Click(object sender, EventArgs e)
  4.        {
  5.            MessageBox.Show("Remember to select the Wireshark \"K12 Text File\" that you have saved with " +
  6.                "the filter 'sap.flags' (no apostrophes) and save \"Packet Range: Displayed\" and \"All packets\"",
  7.                "Instructions", MessageBoxButtons.OK, MessageBoxIcon.Information);
  8.  
  9.            btnSave.Enabled = false;
  10.  
  11.            openWireshackTxtFile.Title = "Choose wireshark txt file";
  12.            openWireshackTxtFile.Filter = "TXT Files|*.txt";
  13.  
  14.            if (openWireshackTxtFile.ShowDialog(this) == DialogResult.OK)
  15.            {
  16.                strWireSharkFileLocation = openWireshackTxtFile.FileName;
  17.  
  18.                replaceBigTextBox("");
  19.                replaceM3UTextBox("");
  20.  
  21.                Thread threadReadHex = new Thread(readHexAndOutputASCII);
  22.                threadReadHex.IsBackground = true;
  23.                threadReadHex.Start();
  24.            }
  25.        }
  26.  
  27.        private void readHexAndOutputASCII()
  28.        {
  29.            if (strWireSharkFileLocation == "VOID")
  30.            {
  31.                return;
  32.            }
  33.  
  34.            try
  35.            {
  36.                strWireSharkFile = File.ReadAllLines(strWireSharkFileLocation);
  37.            }
  38.            catch
  39.            {
  40.                MessageBox.Show("Failed to open Wireshack file", "Fatal error",
  41.                    MessageBoxButtons.OK, MessageBoxIcon.Error);
  42.                return;
  43.            }
  44.  
  45.            replaceM3UTextBox("#EXTM3U\r\n");
  46.  
  47.            int i = 1;
  48.            int j = 0;
  49.  
  50.            foreach (string line in strWireSharkFile)
  51.            {
  52.                if (line.Length > 2 && line.Substring(0, 2) == "|0")
  53.                {
  54.                    string[] characters = line.Split('|');
  55.                    string completeLine = "";
  56.  
  57.                    foreach (string hex in characters)
  58.                    {
  59.  
  60.                        if (hex.Length == 2)
  61.                        {
  62.                            try
  63.                            {
  64.                                int n = Convert.ToInt32(hex, 16);
  65.                                if (n >= 32 && n < 255)
  66.                                {
  67.                                    char c = (char)n;
  68.                                    completeLine += c.ToString();
  69.                                }
  70.                                else if (n == 10)
  71.                                {
  72.                                    completeLine += "|";
  73.                                }
  74.                            }
  75.                            catch
  76.                            {
  77.                                // Do we need to do anything here?
  78.                            }
  79.                        }
  80.                    }
  81.  
  82.                    addToBigTextBox(completeLine.Replace("|", "\r\n") + "\r\r\n");
  83.  
  84.                    string[] partLine = completeLine.Split('|');
  85.  
  86.                    foreach (string data in partLine)
  87.                    {
  88.  
  89.                        if (data.Length > 3 && data.Substring(0, 2) == "s=")
  90.                        {
  91.                            string channelName = data.Substring(2, data.Length - 2);
  92.                            addToM3UTextBox("#EXTINF:" + i + "," + channelName + "\r\n");
  93.                        }
  94.  
  95.                        if (data.Length > 3 && data.Substring(0, 2) == "c=")
  96.                        {
  97.                            string nospacedata = data.Replace(" ", "");
  98.                            string[] splitip = nospacedata.Split('/');
  99.                            string ip = splitip[0].Substring(7, splitip[0].Length - 7);
  100.                            addToM3UTextBox("udp://" + ip + ":5000" + "\r\n");
  101.                        }
  102.  
  103.  
  104.                    }
  105.                    decimal deProgressBar = (((decimal)j + 1) / (decimal)strWireSharkFile.Length) * 100;
  106.                    intProgressBar = (int)Math.Ceiling(deProgressBar);
  107.                    changeProgressBar();
  108.                    i++;
  109.                }
  110.                j++;
  111.            }
  112.            intProgressBar = 100;
  113.            changeProgressBar();
  114.        }
Logged

Learning C# - Graham Robinson
Stoic Joker
Honorary Member
**
Posts: 5,118



View Profile WWW Give some DonationCredits to this forum member
« Reply #9 on: May 03, 2011, 06:54:09 AM »

the more unreliable and inconsistent IPTV systems seem to lock up the .Receive commands.

Hm... Sorry if I get a little Captain Obvious here, but are you sure the request packet is being replicated exactly? The header may need a bit of tweaking to get the device to respond reliably.

If you put receive in its own thread with a small buffer called in a loop you can then get partial output to display which might help to establish where it's hanging and why.

(Sorry man I got nothing in C#, but...) Here's a Quick-N-Dirty example that I cut out of a project:
Formatted for C++ with the GeSHI Syntax Highlighter [copy or print]
  1. // The thread passes a handle to the edit control to the receive function so tell us what's u.
  2.  while(WaitForSingleObject(hStopEvent, 0) != WAIT_OBJECT_0) { // ...When it's Time for it.
  3.  if(bPortChange) {
  4.  SetEvent(hStopEvent);
  5.  }else{
  6.  Listen4Ping(g_hEdit, s);
  7.  }
  8.  }
  9.  
  10. //===========================================================================================
  11. //-------------------------------------------------------------+++--> Tell User What You Hear!
  12. void Listen4Ping(HWND hEdit, SOCKET soc) { //------------------------------------------+++-->
  13. TCHAR recvbuf[MAX_BUFF] = {0};
  14. TCHAR szTemp[GEN_BUFF] = {0};
  15. SOCKADDR_IN saPong; // IP Address Structure for Local Listener.
  16. int iSenderAddrSize = sizeof(saPong);
  17. int iResult;
  18.  
  19. timeval tv; // Time Value Object
  20. fd_set fd; // File Descriptor Set
  21.  
  22.  fd.fd_count = 1; //----//-+++--> Number of sockets in the set.
  23.  fd.fd_array[0] = soc; // Array of sockets that are in the set.
  24.  
  25.  tv.tv_sec = 1;  // Set Timer Value to Wait Only 1 second...
  26.  tv.tv_usec = 0; // With No Additional microseconds to wait.
  27.  
  28.  iResult = select(1, &fd, NULL, NULL, &tv);
  29.  
  30.  if(iResult > 0) {
  31.  SOCKET Accpt;
  32.  int iBytesRecv;
  33.  Accpt = accept(soc,(SOCKADDR *)&saPong, &iSenderAddrSize);
  34.  StringCbPrintf(szTemp, GEN_BUFF, "\r\nConnected Client's IP: %s", inet_ntoa(saPong.sin_addr));
  35.  SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)szTemp);
  36.  iBytesRecv = recv(Accpt, recvbuf, MAX_BUFF, 0);
  37.  SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)recvbuf);
  38.  StringCbPrintf(szTemp, GEN_BUFF, "\r\nBytes Received: %ld\r\n\r\n", iBytesRecv);
  39.  SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)szTemp);
  40.  if(Accpt) closesocket(Accpt);
  41.  }else{
  42.  SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)".");
  43.  }
  44. } // Here I get output of something every second regardless of a connection. That was if something does go wrong is obvious even if it isn't bad enough to lock the entire app.
Logged
mediaguycouk
Supporting Member
**
Posts: 244


see users location on a map View Profile WWW Give some DonationCredits to this forum member
« Reply #10 on: May 03, 2011, 10:42:17 AM »

Quote
Sorry if I get a little Captain Obvious here, but are you sure the request packet is being replicated exactly?
It's the same as the WireShark capture, but past that I can't be 100%.

I've certainly given up on this, so don't spend any more time on it. Once the announce works I've got to query the box for the channels all while programming on a subnet that doesn't actually have the boxes on it.

This project is where an attitude of 'fail quickly and adapt' is working well. The C# application to use the Wireshark data works well enough for how little it would be used.

Thanks all

Graham
Logged

Learning C# - Graham Robinson
Pages: [1]   Go Up
  Reply  |  New Topic  |  Print  
 
Jump to:  
   Forum Home   Thread Marks Chat! Downloads Search Login Register  

DonationCoder.com | About Us
DonationCoder.com Forum | Powered by SMF
[ Page time: 0.11s | Server load: 0.03 ]