Reading off a socket until end of line C#?

Posted by Omar Kooheji on Stack Overflow See other posts from Stack Overflow or by Omar Kooheji
Published on 2010-04-16T15:36:54Z Indexed on 2010/04/16 15:53 UTC
Read the original article Hit count: 500

Filed under:
|

I'm trying to write a service that listens to a TCP Socket on a given port until an end of line is recived and then based on the "line" that was received executes a command.

I've followed a basic socket programming tutorial for c# and have come up with the following code to listen to a socket:

public void StartListening()
        {
            _log.Debug("Creating Maing TCP Listen Socket");
            _mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, _port);
            _log.Debug("Binding to local IP Address");
            _mainSocket.Bind(ipLocal);

            _log.DebugFormat("Listening to port {0}",_port);
            _mainSocket.Listen(10);

            _log.Debug("Creating Asynchronous callback for client connections");
            _mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);

        }

        public void OnClientConnect(IAsyncResult asyn)
        {
            try
            {
                _log.Debug("OnClientConnect Creating worker socket");
                Socket workerSocket = _mainSocket.EndAccept(asyn);
                _log.Debug("Adding worker socket to list");
                _workerSockets.Add(workerSocket);
                _log.Debug("Waiting For Data");
                WaitForData(workerSocket);

                _log.DebugFormat("Clients Connected [{0}]", _workerSockets.Count);

                _mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
            }
            catch (ObjectDisposedException)
            {
                _log.Error("OnClientConnection: Socket has been closed\n");
            }
            catch (SocketException se)
            {
                _log.Error("Socket Exception", se);
            }
        }

        public class SocketPacket
        {
            private System.Net.Sockets.Socket _currentSocket;

            public System.Net.Sockets.Socket CurrentSocket
            {
                get { return _currentSocket; }
                set { _currentSocket = value; }
            }
            private byte[] _dataBuffer = new byte[1];

            public byte[] DataBuffer
            {
                get { return _dataBuffer; }
                set { _dataBuffer = value; }
            }


        }

        private void WaitForData(Socket workerSocket)
        {
            _log.Debug("Entering WaitForData");
            try
            {
                lock (this)
                {
                    if (_workerCallback == null)
                    {
                        _log.Debug("Initializing worker callback to OnDataRecieved");
                       _workerCallback = new AsyncCallback(OnDataRecieved);
                    }
                }
                SocketPacket socketPacket = new SocketPacket();
                socketPacket.CurrentSocket = workerSocket;
                workerSocket.BeginReceive(socketPacket.DataBuffer, 0, socketPacket.DataBuffer.Length, SocketFlags.None, _workerCallback, socketPacket);
            }
            catch (SocketException se)
            {
                _log.Error("Socket Exception", se);
            }
        }

        public void OnDataRecieved(IAsyncResult asyn)
        {
            SocketPacket socketData = (SocketPacket)asyn.AsyncState;
            try
            {

                int iRx = socketData.CurrentSocket.EndReceive(asyn);
                char[] chars = new char[iRx + 1];
                _log.DebugFormat("Created Char array to hold incomming data. [{0}]",iRx+1);

                System.Text.Decoder decoder = System.Text.Encoding.UTF8.GetDecoder();
                int charLength = decoder.GetChars(socketData.DataBuffer, 0, iRx, chars, 0);
                _log.DebugFormat("Read [{0}] characters",charLength);

                String data = new String(chars);
                _log.DebugFormat("Read in String \"{0}\"",data);

                WaitForData(socketData.CurrentSocket);
            }
            catch (ObjectDisposedException)
            {
                _log.Error("OnDataReceived: Socket has been closed. Removing Socket");
                _workerSockets.Remove(socketData.CurrentSocket);

            }
            catch (SocketException se)
            {
                _log.Error("SocketException:",se);
                _workerSockets.Remove(socketData.CurrentSocket);

            }
        }

This I thought was going to be a good basis for what I wanted to do, but the code I have appended the incoming characters to a text box one by one and didn't do anything with it. Which doesn't really work for what I want to do.

My main issue is the decoupling of the OnDataReceived method from the Wait for data method. which means I'm having issues building a string (I would use a string builder but I can accept multiple connections so that doesn't really work.

Ideally I'd like to look while listening to a socket until I see and end of line character and then call a method with the resulting string as a parameter.

What's the best way to go about doing this.

© Stack Overflow or respective owner

Related posts about c#

Related posts about sockets