如何在C#中使用RAW TCP连接执行命令

时间:2018-01-17 08:21:44

标签: c# tcp connection

创建C#脚本时,我能够连接到TCP,但无法执行任何命令,如登录等...

执行RQ01,R01,10,CLI,CNUM

的示例命令

在旁注上我能够从上面的命令使用PuTTY获得响应,但是无法在C#代码中执行命令。

我的代码:

try {
    // Create a TcpClient.
    // Note, for this client to work you need to have a TcpServer 
    // connected to the same address as specified by the server, port
    // combination.
    TcpClient client = new TcpClient("xxx.xxx.xx.x", 2131);
    var message = "LOGIN,10,SUGARDEV,CLEF";
    // Translate the passed message into ASCII and store it as a Byte array.
    Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

    // Get a client stream for reading and writing.
    //  Stream stream = client.GetStream();

    NetworkStream stream = client.GetStream();

    // Send the message to the connected TcpServer. 
    stream.Write(data, 0, data.Length);

    Console.WriteLine("Sent: {0}", message);

    // Receive the TcpServer.response.

    // Buffer to store the response bytes.
    data = new Byte[256];

    // String to store the response ASCII representation.
    String responseData = String.Empty;

    // 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);
    Console.WriteLine("Received: {0}", responseData);
    //var message = "LOGIN,10,SUGARDEV,CLEF";
    // Translate the passed message into ASCII and store it as a Byte array.
    //Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

    // Get a client stream for reading and writing.
    //  Stream stream = client.GetStream();


    // Send the message to the connected TcpServer. 
    stream.Write(data, 0, data.Length);
    bytes = stream.Read(data, 0, data.Length);
    responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
    // Close everything.
    //stream.Close();
    //client.Close();
} catch (ArgumentNullException e) {
    Console.WriteLine("ArgumentNullException: {0}", e);
}
Console.WriteLine("\n Press Enter to continue...");

Console.Read();

1 个答案:

答案 0 :(得分:0)

首先,您必须选择是否使用异步或同步通信。同步是最简单的,您发送命令并等待响应到达。然后你可以有一个状态机来定义你在沟通过程中的位置:

  1. SendCommand - 使用stream.Write()
  2. 发送命令
  3. AwaitResponse - 等待一段时间,让响应到达,或者在设定的时间段后超时。
  4. ParseResponse - 验证响应是否符合预期,如果响应不正确(校验和失败等),可能会重新发送命令。
  5. 或者您可以使用异步通信,您可以在其中发送命令并且不等待响应 - 响应将由其他代码处理。然后,您需要在单独的线程中使用RX处理程序,它始终等待传入的数据,并将其发送到某个缓冲区。然后,在发送命令后,您可以继续执行其他操作并稍后再回来查看响应是否已到达。

    编辑:我的偏好通常是异步通信,因为它会导致应用程序中的延迟最小。如何实现它取决于通信协议,如果它是,例如ASCII字符串或复杂的二进制协议。

    这是来自异步实现的RX处理程序的片段。这是串行通信线路上的二进制协议,因此必须逐个验证每个接收到的字节。

    public class Message
    {
        public Message()
        {
            Payload = new Payload();
            RawData = new List<byte>();
        }
    
        public byte Address { get; set; }
        public byte Length { get; set; }
        public Payload Payload { get; set; }
        public byte Checksum { get; set; }
        public List<byte> RawData { get; set; }
    }
    
    enum RxState
    {
        AwaitStartCharacter,
        AwaitLengthCharacters,
        AwaitPayloadCharacters,
        AwaitChecksumCharacters
    }
    
    private void RxBufferQueueConsumer()
    {
        var rxState = RxState.AwaitStartCharacter;
        Message rxMessage = null;
        while (!_cts.IsCancellationRequested)
        {
            CheckRxBufferQueue(ref rxState, ref rxMessage);
        }
    }
    
    private BlockingCollection<byte> _rxBufferQueue;
    private CancellationTokenSource _cts;
    
    private void CheckRxBufferQueue(ref RxState rxState, ref Message rxMessage)
    {
        byte rxByte;
        if (_rxBufferQueue.TryTake(out rxByte, 50))
        {
            switch (rxState)
            {
                case RxState.AwaitStartCharacter:
                    AwaitStartCharacter(ref rxState, rxByte, ref rxMessage);
                    break;
    
                case RxState.AwaitLengthCharacters:
                    AwaitLengthCharacters(ref rxState, rxByte, ref rxMessage);
                    break;
    
                case RxState.AwaitPayloadCharacters:
                    AwaitPayloadCharacters(ref rxState, rxByte, ref rxMessage);
                    break;
    
                case RxState.AwaitChecksumCharacters:
                    AwaitChecksumCharacters(ref rxState, rxByte, ref rxMessage);
                    break;
            }
        }
    }