0

I have a barcode scanner hardware device that continually scans barcodes passing passing by and sends the data through it's tcpip port. The scanner is installed on a production line and reads all passing barcodes for verification purposes. There isn't any information sent to the barcode scanner other than what might be sent through the NetworkStream class upon connection. I implemented a very simple interface to verify connectivity and receipt of the expected data being sent by the device. Obviously the problem with this code is it only iterates a certain number of times. Regardless of the looping choice, I need an app that receives data and continues to receive data until my code chooses to stop close the connection and stop receipt of data. It has to always be watching the port for incoming data from the device's tcp ip server.

public void readData()
    {
        int n = 1;

            Byte[] data;
            Int32 port = 51236;
            TcpClient client = new TcpClient("192.168.0.70", port);
            NetworkStream stream = client.GetStream();
            String responseData = String.Empty;
            try
            {
                while (n < 50)
                {
                data = new Byte[256];  //arbitrary length for now

                // String to store the response ASCII representation.

                // Read the first batch of the TcpServer response bytes.
                Int32 bytes = stream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                m_upcCode = responseData;
                n++;
                }
            }
            catch (ArgumentNullException ArgEx)
            {
                m_upcCode = "ArgumentNullException: {0}" + ArgEx.Message.ToString();
            }
            catch (SocketException exSocket)
            {
                m_upcCode = "SocketException: {0}" + exSocket.Message.ToString();
            }
    }

I've been looking through numerous posts regarding establishing a connection to a tcp ip server and receiving data from the server. The post I found with the most promise might be Can a TCP c# client receive and send continuously/consecutively without sleep?. I'm just having an issue understanding how to implement the design. I would be happy just to see the code from that post simply called and implemented on a form and display data in a text box. The data being received is always a fixed length of 12 digits of a bar code and a . The data doesn't stop unless the conveyor belt stops. But we don't want the connection to close just because of a line pause. There was also a post at C# TCP Client listening for data specifically trying to address reading barcodes but didn't get much of a response.

Community
  • 1
  • 1
pkColorado
  • 11
  • 1
  • 5
  • Here's an answer that seems close to what you're attempting: http://stackoverflow.com/questions/21600011/read-continous-bytestream-from-stream-using-tcpclient-and-reactive-extensions – BadHeuristics Apr 21 '17 at 20:59
  • This API seems to have poor documentation. Allegedy `NetworkStream` performs *blocking* I/O, which means that its `read()` method shouldn't return until there is at least *some* data available, or there's an error - but the error possibilities seem to be handled by exceptions. It's unclear then what could cause read() to return anything but a positive value. If this is actually a legitimate blocking read, then all you need to do is call it, let the system sleep (ie block) your program until some data is available, use that data, and repeat until you're done or get an exception. – Chris Stratton Jul 20 '17 at 06:20

2 Answers2

0

Take out the counter completely. When you do a read and there are zero bytes returned, put the thread to sleep momentarily, and loop.

public void readData()
{
    Byte[] data;
    Int32 port = 51236;
    TcpClient client = new TcpClient("192.168.0.70", port);
    NetworkStream stream = client.GetStream();
    String responseData = String.Empty;
    try
    {
        while (true)
        {
            data = new Byte[256];  //arbitrary length for now

            // String to store the response ASCII representation.

            // Read the first batch of the TcpServer response bytes.
            Int32 bytes = stream.Read(data, 0, data.Length);
            if (bytes == 0){
                System.Threading.Thread.Sleep(1000);
            }
            else {
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                m_upcCode = responseData;
            }
        }
    }
    catch (ArgumentNullException ArgEx)
    {
        m_upcCode = "ArgumentNullException: {0}" + ArgEx.Message.ToString();
    }
    catch (SocketException exSocket)
    {
        m_upcCode = "SocketException: {0}" + exSocket.Message.ToString();
    }
}
Xavier J
  • 4,326
  • 1
  • 14
  • 25
-1

Maybe this code can help you. It's a TCP server i wrote for a connector (protocol conversion) application. It can only handle one connection from one client. It run's a separate thread and can be controlled trough some public methods. It raises event's to communicate with other code. You might need to alter some code (for example the logging part). I hope it helps you.

public class TCPServer : ITCPServer
{
    private readonly IPEndPoint _ipEndPoint;
    private TcpListener _tcpListener;
    private TcpClient _tcpClient;
    private bool _runServer;
    private bool _connectToClient;
    private NetworkStream _networkStream;
    private volatile bool _isRunning;

    public TCPServer(IPEndPoint ipEndpoint)
    {
        _ipEndPoint = ipEndpoint;
    }

    #region Properties

    public bool IsRunning
    {
        get { return _isRunning; }
    }

    #endregion

    #region Events

    public event Action<byte[]> OnMessageReceived;
    public event Action<string> OnConnectionOpened;
    public event Action<string> OnConnectionClosed;
    public event Action<LogLevel, string> OnLogMessage;

    #endregion

    #region Public Methods

    public void Start()
    {
        _tcpListener = new TcpListener(_ipEndPoint);
        _runServer = true;
        _tcpListener.Start();

        var thread = new Thread(RunServerEngine);
        thread.Name = "TcpServer";
        thread.Start();

        while (!_isRunning)
        {
        }

        var localEndpoint = (IPEndPoint)_tcpListener.LocalEndpoint;
        RaiseOnLogMessage(LogLevel.Info, String.Format("Server started listening at ip address {0} on port {1}", localEndpoint.Address, localEndpoint.Port));
    }

    public void Stop()
    {
        _connectToClient = false;
        _runServer = false;
    }

    public void SendMessage(byte[] message)
    {
        _networkStream.Write(message, 0, message.Length);
        _networkStream.Flush();
    }

    public void DisconnectClient()
    {
        _connectToClient = false;
    }

    #endregion

    #region Private Methods

    private void RunServerEngine(Object obj)
    {
        try
        {
            _isRunning = true;

            while (_runServer)
            {
                Thread.Sleep(250);
                if (_tcpListener.Pending())
                {
                    using (_tcpClient = _tcpListener.AcceptTcpClient())
                    {
                        var socketForClient = _tcpClient.Client;
                        _networkStream = new NetworkStream(socketForClient);
                        RaiseOnConnectionOpened((IPEndPoint)_tcpClient.Client.RemoteEndPoint);
                        _connectToClient = true;

                        while (_connectToClient)
                        {
                            if (CheckClientConnection() == false)
                            {
                                _connectToClient = false;
                                break;
                            }

                            if (_networkStream.DataAvailable)
                            {
                                var bytes = new Byte[1024];
                                _networkStream.Read(bytes, 0, 1024);
                                bytes = bytes.TakeWhile(b => b > 0).ToArray();
                                RaiseOnMessageReceived(bytes);
                            }

                            Thread.Sleep(100);
                        }
                    }
                    RaiseOnConnectionClosed();
                }
            }

            RaiseOnLogMessage(LogLevel.Info, "Stopping TCP Server");
            _tcpListener.Stop();
            _isRunning = false;
            RaiseOnLogMessage(LogLevel.Info, "TCP Server stopped");
        }
        catch (Exception ex)
        {
            RaiseOnLogMessage(LogLevel.Error, String.Format("Fatal error in TCP Server, {0}", ex.ToString()));
            throw;
        }
    }


    private bool CheckClientConnection()
    {
        var connected = true;

        try
        {
            var pollResult = _tcpClient.Client.Poll(1, SelectMode.SelectRead);
            var dataAvailable = _tcpClient.Client.Available;
            connected = !(pollResult && _tcpClient.Client.Available == 0);

            if (!connected)
            {
                RaiseOnLogMessage(LogLevel.Info, "Detected disconnection from client");
                RaiseOnLogMessage(LogLevel.Info, String.Format("TCPServer.CheckClientConnection - connected: {0}, pollResult: {1}, dataAvailable: {2}", connected, pollResult, dataAvailable));
            }
        }
        catch (SocketException ex)
        {
            RaiseOnLogMessage(LogLevel.Info, String.Format("Exception occurred in TCPServer.CheckClientConnection. Ex: {0}", ex.ToString()));
            connected = false;
        }

        return connected;
    }

    private void RaiseOnMessageReceived(byte[] message)
    {
        if (OnMessageReceived != null)
        {
            try
            {
                OnMessageReceived(message);
            }
            catch (Exception ex)
            {
                RaiseOnLogMessage(LogLevel.Warning, ex.Message);
            }
        }
    }

    private void RaiseOnConnectionOpened(IPEndPoint remoteEndpoint)
    {
        if (OnConnectionOpened != null)
        {
            var msg = String.Format("Connected to client with ip address: {0}, port: {1}", remoteEndpoint.Address, remoteEndpoint.Port);
            OnConnectionOpened(msg);
        }
    }

    private void RaiseOnConnectionClosed()
    {
        if (OnConnectionClosed != null)
            OnConnectionClosed("Disconnected from client");
    }

    private void RaiseOnLogMessage(LogLevel level, string message)
    {
        if (OnLogMessage != null)
            OnLogMessage(level, message);
    }

    #endregion
}
Jimmy Hannon
  • 729
  • 5
  • 14
  • 1
    Since my application is entirely on the client side, most of this is inapplicable however, the small portion of NetworkStream code and checking for DataAvailable might be something I can utilize. Thanks. – pkColorado Apr 25 '17 at 18:06