Click here to Skip to main content
13,150,622 members (44,170 online)
Click here to Skip to main content
Add your own
alternative version

Stats

60.7K views
9.9K downloads
68 bookmarked
Posted 1 Mar 2012

Send and receive messages in a LAN with broadcasting

, 29 Feb 2012
Rate this:
Please Sign up or sign in to vote.
Lightweight library for generic LAN UDP broadcasting
This is an old version of the currently published article.

Introduction

Orekaria.Lib.P2P is a library that I have written to encapsulate and simplify the process of sending and receiving untargeted packets in a local area network (LAN). It operates at UDP level. It´s very useful when you want quick LAN logic or when you want to understand the basics of UDP broadcasting. Its optional encryption mode gives you the power to send packets in any LAN ensuring that although the message could be received for any computer on that LAN, only the ones with your key could read the content.

Possible uses could be:

  • LAN code tests.
  • P2P logic.
  • LAN chat.
  • LAN indie games.
  • Server discovery instructions. A client ask for a server. Then, a server answers with a IP and port to which the client can connect.
  • etc.

Using the library

The use of the library is pretty straightforward.

  1. Add the library: Download the .dll and place it in your project. Add a reference to that library.
  2. Declaration and initialization
  3. Broadcasting messages
  4. Receiving broadcasted messages
  5. Disposing

Quick Start

Maybe one of the smallest programs we could write to show how this library work is a console chat. The program will be able to receive any message sent to Lan, decript it and show it on the console. It will also be able to send a user message to Lan. The program uses a thread to show the messages received as they are received. The library is thread safe. Here is the code of this tiny example:

using System;
using System.Threading;
using Orekaria.Lib.P2P; 
namespace Orekaria.Test.P2P.ConUI
{
    class Program : IDisposable
    {
        P2PHelper _p2p;
        Thread _th;
        Program()
        {
            _p2p = new P2PHelper(8000, "OZ#5T3/6D)6?t3");
            _th = new Thread(DequeueMessages);
            _th.Start();
        }
        void Run()
        {
            var isExit = false;
            do
            {
                var s = Console.ReadLine();
                if (s.ToLower() == "exit")
                    isExit = true;
                else
                    _p2p.Send(string.Format("{0}: {1}", Environment.UserName, s));
            } while (!isExit);
        }
        public void Dispose()
        {
            _th.Abort();
            _p2p.Dispose();
        }
        private void DequeueMessages()
        {
            while (_th.IsAlive)
            {
                Thread.Sleep(100);
                while (_p2p.Received.Count > 0)
                    Console.WriteLine(string.Format("{0}", _p2p.Received.Dequeue()));
            }
        }
        static void Main(string[] args)
        {
            var p = new Program();
            p.Run();
            p.Dispose();
        }
    }
} 

Key lines are bold-ed and italic-ed. The library is declared in the first lines and a new thread is started to show the messages as soon as they are received. Then the process keeps reading the user console until "exit" is typed. The send method is the one responsible for broadcasting the messages. You would like to test this example in a LAN to see how messages are received by everybody on LAN.Notice that the Dispose method finishes the thread and also disposes the p2pHelper. This is absolutely necessary if you don´t want to leave the thread alive in memory.

The output when 2 users called DAM and ASIR are executing this code is this. The first line "ASIR: Hello DAM" being the remote computer, the line "Hello" being the local user writing a response and "DAM: Hello" being the local echo of that response that have been broadcasted and then received back:

p2pCon.png

About the examples included

The examples included extend the use of the library to specific goals. The first one is a Wpf LAN chat and the second one is a Forms LAN game called "Sink the boat". The chat is quite the same as the above console example but translated to very basic Wpf code. The LAN game is more complex because it demonstrates how this library could be use to send packed messages or serialized content. These are some decripted messages that are broadcasted in this LAN game:

p2pBoatMsg.png

When one of these messages is received, the code below depacks the information within the message. Is not important how they are packed as you should use your own but its shown here for demonstration purpouses:

Private Sub ProcesaPaquete(messageReceived As String)
    Dim parts = messageReceived.Split(" ")
    Dim hostEmitter = CatalogHost(parts(0))
    If parts.Length = 2 Then
        hostEmitter.PingReceived(Convert.ToInt32(parts(1)))
        Return
    End If
    Dim target = parts(1)
    Dim hostTarget = LogHost(target)
    Dim mb = New processParts(messageReceived, Convert.ToInt32(parts(2)), parts(3))
    hostTarget.MessageReceived(mb)
End Sub

In the code above, the received message is unpacked and the information is classified in one of three categories: ping, shoot or impact. Each of these, containing different information that is processed afterwards.

The magic inside the library

The library is formed by two classes. One is called P2PHelper and the other one is called UDPHelper. As a side note, this is a project much bigger than the one presented here and so the name P2PHelper. This class, P2PHelper, is the only public exposed class. Three methods and a property are visible: the constructor, Dispose, Send and Received.

When P2PHelper is instanciated, two threads are created, each one containing an instance of the UDPHelper class. The UDPHelper class encapsulates and simplifies the System.Net.Sockets.UdpClient and the System.Text.Encoding. You may like to change your preferred encoding here.

Listening and talking to the LAN

One of the threads is for listening and the other one is for talking. I must point here as I did in the code, that both threads could be use for listening and speaking having a total of 2x2.

The listening thread (called server in the code), needs some specific parameters to enter the broadcast listener mode. Keys are IPAddress.Any to listen any other in the LAN and timeout to allow the thread to exit the listening state:

var udpServer = new UdpClient(new IPEndPoint(IPAddress.Any, _port)) {Client = {ReceiveTimeout = TimeOut}};
var serverEP = new IPEndPoint(IPAddress.Any, 0);
var server = new UDPHelper(udpServer, serverEP);

The talking thread (called client in the code), although using the same UDPHelper class, needs other specific parameters to enter the broadcast talking mode. Keys are EnableBroadcast = true, IPAddress.Broadcast and the port we are talking through:

var udpClient = new UdpClient {EnableBroadcast = true, Client = {ReceiveTimeout = TimeOut}};
var clientEP = new IPEndPoint(IPAddress.Broadcast, _port);
var client = new UDPHelper(udpClient, clientEP); 

If you are interested in tweaking and improving this code you should have enough room tweaking this class, in particular the parameters sent to the UDPHelper class explained above. You will see how some changes do still work and some other fail.

After this two threads are created, the P2PHelper keeps listening and enqueueing the messages received. If encryption is enabled, the messages are decrypted:

while (!_disposing) {
    var receive = server.Receive();
    if (receive != Resources.TimeOut)
        _received.Enqueue(_encript ? EncriptHelper.DecryptString(receive, _passPhrase) : receive);
    Thread.Sleep(1);
}  

and talking. If encryption is enabled, messages are encrypted:

while (!_disposing) {
    while (_toSend.Count > 0) {
    var send = _toSend.Dequeue();
        client.Send(_encript ? EncriptHelper.EncryptString(send, _passPhrase) : send);
    }
    Thread.Sleep(10);
}  
Disposing

Disposing the object is required to free the resources. You may want to improve this code to fit your needs or even to work without this explicit disposing.

public void Dispose()
{
    _disposing = true;
    _thClient.Join();
    _thServer.Join();
}  

Points of Interest

The most interesting point about this library is that encapsulates all the UDP broadcasting logic in an easy to use multithreaded wrapper.

It specifically solves common difficulties regarding a port being in use when trying to send and receive at the same time; and with the udp listener waiting forever to receive packets. The first one is solved with the right parameters in the udpClient and the second one setting a timeout to the receiver internal thread.

The queue inside the Received method allows the programmer to use the library safety in any thread.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Orekaria
Software Developer (Senior)
Spain Spain
Hi, I am a Senior Generalist SDE and I have 25+ years of software development experience. My eyes, hands and brain have traveled from Spectrum Basic/assembler all the way to C++, Java and C#. In recent years I have been gluing electronics and software.

I have some Microsoft certifications along with others that I have forgotten.

http://orekaria.com

You may also be interested in...

Comments and Discussions

Discussions on this specific version of this article. Add your comments on how to improve this article here. These comments will not be visible on the final published version of this article.
 
QuestionThe port? Pin
Member 1106507227-Apr-15 17:46
memberMember 1106507227-Apr-15 17:46 
QuestionPlease Someone Help me Out regarding this Project. Pin
Member 1034600525-Oct-13 22:13
memberMember 1034600525-Oct-13 22:13 
GeneralMy vote of 5 Pin
Mazen el Senih9-Jun-12 8:16
memberMazen el Senih9-Jun-12 8:16 
GeneralNice ! Pin
raananv10-Mar-12 8:37
memberraananv10-Mar-12 8:37 
Generalthank you very good! Pin
kartalyildirim2-Mar-12 6:01
memberkartalyildirim2-Mar-12 6:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.


Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170924.2 | Last Updated 29 Feb 2012
Article Copyright 2012 by Orekaria
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid