יום חמישי, 21 באוקטובר 2010

.net Blocking Socket

Hi

In this post I will show how to use blocking socket in .net.

First thing is first what is blocking socket?

Well socket is one way to send byte array through the net ,blocking means that while the send/receive operation is taking place the thread is blocked until time out expires.

In this post I will focus on the client side (on the server side there is a listening socket).
In this example the client sends and receive byte arrays that are not fix in size ,that means that the client needs to calculate the length of the incoming byte array.To do this the client and server have an agreement that the first 4 byte in the array represent the length of the message, that means that the client while receiving a message reads the first 4 bytes converts them to an integer and reads the reset of the message.When the client sends a message it adds the length of the byte array as a prefix before sending it to the server.

In this post you can see that the client handles connection problems and can reconnect when needed.
It is important that the client will recognize that it needs to recontact to the server.To do this I used socket time out ,when sending the socket tells if there is a connection problem so this is easy to handle but when receiving the socket is not aware to connection problems and is in blocking mode so I used time outs to get around this predicament.It is important to know that when time out expires the socket can not be reused so the it needs to reconnect.

Code Example:
public class ClientReceiver
    {

        private Thread receiver;
        private IPEndPoint ipep;
        private Socket server;
        private int sessions, interval;

        public ClientReceiver()
        {

        }

        public void Start(IPAddress ip, int port, int sessions, int interval)
        {
            this.sessions = sessions;
            this.interval = interval;
            ipep = new IPEndPoint(ip, port);
            receiver = new Thread(Do);
            receiver.IsBackground = true;
            receiver.Start();
        }

        private void Do()
        {          
            for (int k = 0; k < sessions; k++)
            {
                Socket service = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                service.Connect(ipep);
                Console.WriteLine("Connecting.....");
                if (service.Connected)
                {
                    byte[] receiveddata;
                    int j = 0;
                    try
                    {
                        if (SendAck(service))
                        {
                            while (j < interval)
                            {                           
                                if (Receive(service, out receiveddata))
                                {
                                    Console.WriteLine(string.Format("Received: {0} in session {1}", j, k));
                                    j++;
                                }
                            }

                        }   
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
                Console.WriteLine("Disconnecting......");
                CloseConnection(service);  

            }

        }

        private void CloseConnection(Socket s)
        {
            try
            {
                s.Shutdown(SocketShutdown.Both);
            }
            catch 
            {               
               
            }
            s.Close();
        }


        private bool Receive(Socket s, out byte[] DataReceived)
        {
            int total = 0;
            int recv = 0;
            int size = 0;
            byte[] datasize = new byte[4];
            try
            {
                while ((recv = s.Receive(datasize, 0, 4, 0)) < 4)
                {
                    if (recv == 0)
                    {//problem                            
                        DataReceived = null;
                        return false;
                    }
                    recv += s.Receive(datasize, 0, 4, 0);
                }
                size = BitConverter.ToInt32(datasize, 0);
                int dataleft = size;
                byte[] data = new byte[size];
                while (total < size)
                {
                    if (recv == 0)
                    {//problem                            
                        DataReceived = null;
                        return false;
                    }
                    recv = s.Receive(data, total, dataleft, SocketFlags.None);
                    total += recv;
                    dataleft -= recv;
                }
                DataReceived = data;
                return SendAck(s);

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                DataReceived = null;
                return false;
            }

        }

        public bool SendAck(Socket s)
        {
            byte[] datasize = new byte[4];
            byte[] data = BitConverter.GetBytes(0);
            int total, size, dataleft, sent;
            try
            {
                total = 0;
                size = data.Length;
                dataleft = size;
                datasize = BitConverter.GetBytes(size);
                sent = s.Send(datasize);//send size of object                
                while (total < size)//send the object
                {
                    sent = s.Send(data, total, dataleft, SocketFlags.None);
                    total += sent;
                    dataleft -= sent;
                }
                return true;

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;

            }
        }
    }

אין תגובות:

הוסף רשומת תגובה