【问题标题】:Receiving blocks of data from a TCP IP hardware device using c#使用 c# 从 TCP IP 硬件设备接收数据块
【发布时间】:2017-09-18 23:27:27
【问题描述】:

我有一个条形码扫描仪硬件设备,它不断扫描经过的条形码并通过它的 tcpip 端口发送数据。扫描仪安装在生产线上,读取所有通过的条形码以进行验证。除了在连接时可能通过 NetworkStream 类发送的信息之外,没有任何信息发送到条形码扫描仪。我实现了一个非常简单的接口来验证设备发送的预期数据的连接和接收。显然,这段代码的问题是它只迭代了一定次数。无论循环选择如何,我都需要一个接收数据并继续接收数据的应用程序,直到我的代码选择停止关闭连接并停止接收数据。它必须始终监视端口以获取来自设备的 tcp ip 服务器的传入数据。

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();
            }
    }

我一直在浏览许多关于建立与 tcp ip 服务器的连接并从服务器接收数据的帖子。我发现最有希望的帖子可能是Can a TCP c# client receive and send continuously/consecutively without sleep?。我只是在理解如何实现设计时遇到问题。我很高兴看到该帖子中的代码在表单上简单地调用和实现,并在文本框中显示数据。接收的数据始终是固定长度的 12 位条形码和 .除非传送带停止,否则数据不会停止。但是我们不希望仅仅因为线路暂停而关闭连接。 C# TCP Client listening for data 也有一个帖子,专门尝试解决读取条形码的问题,但没有得到太多回应。

【问题讨论】:

  • 这里的答案似乎与您的尝试接近:stackoverflow.com/questions/21600011/…
  • 这个 API 的文档似乎很差。据称NetworkStream 执行阻塞 I/O,这意味着它的read() 方法不应该返回,直到至少有一些 数据可用,或者出现错误 -但错误的可能性似乎是由异常处理的。目前还不清楚是什么导致 read() 返回正值以外的任何内容。如果这实际上是一个合法的阻塞读取,那么您需要做的就是调用它,让系统休眠(即阻塞)您的程序,直到一些数据可用,使用该数据,然后重复直到完成或出现异常.

标签: c# barcode-scanner tcp-ip hardware-interface


【解决方案1】:

完全取出柜台。当您执行读取并返回零字节时,让线程暂时休眠,然后循环。

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();
    }
}

【讨论】:

  • 谢谢。我会尝试一下并继续调整代码。
【解决方案2】:

也许这段代码可以帮助你。 这是我为连接器(协议转换)应用程序编写的 TCP 服务器。它只能处理来自一个客户端的一个连接。它运行是一个单独的线程,可以通过一些公共方法进行控制。它引发事件以与其他代码进行通信。您可能需要更改一些代码(例如日志记录部分)。希望对你有帮助。

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
}

【讨论】:

  • 由于我的应用程序完全在客户端,所以大部分都不适用,但是,NetworkStream 代码的一小部分和检查 DataAvailable 可能是我可以利用的东西。谢谢。
猜你喜欢
  • 2012-08-09
  • 2011-09-13
  • 2011-02-28
  • 2016-05-09
  • 1970-01-01
  • 2016-11-06
  • 2015-10-22
  • 2022-06-29
  • 1970-01-01
相关资源
最近更新 更多