每次读取时,TelNet接收到的数据都不同

本文关键字:数据 读取 TelNet | 更新日期: 2023-09-27 18:05:52

我有一个小项目要做,涉及从TelNet客户端接收输入,并根据输入做一些处理并返回信息给客户端。

我现在已经得到了大多数工作,一个线程中的侦听器和侦听器接收的每个客户端然后给出它自己的线程。这工作得很好,没有任何错误。当客户端有一些文本输入到它并且在我的代码中接收这些文本时,问题就发生了,我在逐个按键的基础上接收到的内容是正确的,但是当我将它存储在状态对象中时,我得到了一些奇怪的结果。

这是在侦听器接收到新的客户端连接时创建的类,它也用于与TelNet客户端通信:

internal class TelNetClient
{
    Socket _socket;
    public TelNetClient(Socket socket)
    {
        var t = new Thread(() => RealStart(socket));            
        t.Start();
    }
    private void RealStart(Socket socket) 
    {
        this.ClientSocket = socket;
    }
    public Socket ClientSocket
    {
        set
        {
            StateObject stateObject;
            DeviceConnection deviceConnection = new DeviceConnection();
            _socket = value;
            stateObject = new StateObject();
            stateObject.WorkSocket = _socket;
            Send(_socket, "Welcome");
            _socket.BeginReceive(stateObject.Buffer, 0, StateObject.BufferSize, 0, 
                new AsyncCallback(ReadCallBack), stateObject);
        }
    }
    internal void ReadCallBack(IAsyncResult asyncResult)
    {
        string content = string.Empty;
        int bytesRead;
        StateObject stateObject;
        DeviceConnection deviceConnection = new DeviceConnection();
        stateObject = (StateObject)asyncResult.AsyncState;
        bytesRead = _socket.EndReceive(asyncResult);
        if (bytesRead > 0)
        {
            ASCIIEncoding ascii = new ASCIIEncoding();
            stateObject.StringBuilder.Append(ascii.GetString(stateObject.Buffer,
                 0, bytesRead));
            content = stateObject.StringBuilder.ToString();
            if (content.EndsWith(deviceConnection.BarcodeTerminator))
            {
                Send(_socket, Environment.NewLine + ">>>>>" + content + "<");
            }
            else
            {
                _socket.BeginReceive(stateObject.Buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReadCallBack), stateObject);
            }
        }
    }
    internal void Send(Socket socket, string data)
    {
        Byte[] byteData;
        byteData = Encoding.ASCII.GetBytes(data);
        socket.BeginSend(byteData, 0, byteData.Length, 0, 
            new AsyncCallback(SendCallBack), socket);
    }
    internal void SendCallBack(IAsyncResult asyncResult)
    {
        int bytesSent;
        Socket socket;
        StateObject stateObject;
        stateObject = new StateObject();
        stateObject.WorkSocket = _socket;
        socket = (Socket)asyncResult.AsyncState;
        bytesSent = socket.EndSend(asyncResult);
        _socket.BeginReceive(stateObject.Buffer, 0, StateObject.BufferSize, 0, 
            new AsyncCallback(ReadCallBack), stateObject);
    }

StateObject对象如下:

internal class StateObject
{
    internal const int BufferSize = 1024;
    internal Socket WorkSocket = null;
    internal Byte[] Buffer = new Byte[BufferSize];
    internal StringBuilder StringBuilder = new StringBuilder();
}

这大部分可能不是必需的,但我把它们都展示出来,以便人们可以看到完整的图片。

问题在于ReadCallBack方法,正如您可以看到的,我读取字节数组并将其解码为字符串,然后将其附加到StateObject类中的StringBuilder。每次解码的值都是正确的,但是当调用stateObject.StringBuilder.ToString()时,输出不正确,但它是100%可预测的。下面是一个例子:

Key Press Count | Input from TelNet Client | StrinBuilder.ToString() Output      
---------------------------------------------------------------------------
        1       |             A            |                A
        2       |             B            |                B
        3       |             C            |                AC
        4       |             D            |                BD
        5       |             E            |                ACE
        6       |             F            |                BDF

正如您所看到的,最后一个字符总是正确的,但是前面的字符应该是前面的输入连接在一起,正如您所期望的StringBuilder。在我所有的各种测试中,这种情况100%发生。这几乎就像StringBuilder丢失了偶数/奇数字符,但在下一次迭代中又找到了它们!

我已经尝试将StringBuilder更改为string,但同样的问题发生。

有没有人知道为什么会发生这种情况以及如何修复它?

每次读取时,TelNet接收到的数据都不同

您正在创建两个StateObject实例:一个在set_ClientSocket中,另一个在SendCallback中。它们最终都作为两个单独的BeginReceive调用的一部分传递给ReadCallback。看起来每个实例都在接收其他字符。