TCP/IP 解码时 c# 参数中的套接字为 null

TCP/IP Sockets in c# argument null while decoding

我认为最容易解决我的问题的方法就是 post 项目 here。但这行不通。

下面是我认为出错的部分:

public class ItemQuoteDecoderText : ItemQuoteDecoder
{
    //Character encoding
    public Encoding encoding;

    public ItemQuoteDecoderText() : this(ItemQuoteTextConst.DEFAULT_CHAR_ENC) { }

    public ItemQuoteDecoderText(string encodingDesc)
    {
        encoding = Encoding.GetEncoding(encodingDesc);
    }

    public ItemQuote decode(Stream wire)
    {
        string itemNo, description, quant, price, flags;

        byte[] space = encoding.GetBytes(" ");
        byte[] newline = encoding.GetBytes("\n");

        itemNo = encoding.GetString(ItemQuoteFramer.nextToken(wire, space));
        description = encoding.GetString(ItemQuoteFramer.nextToken(wire, newline));
        quant = encoding.GetString(ItemQuoteFramer.nextToken(wire, newline));
        price = encoding.GetString(ItemQuoteFramer.nextToken(wire, newline));
        flags = encoding.GetString(ItemQuoteFramer.nextToken(wire, newline));

        return new ItemQuote(Int64.Parse(itemNo),
                                description,
                                Int32.Parse(quant),
                                Int32.Parse(price),
                                (flags.IndexOf('d') != -1),
                                (flags.IndexOf('s') != -1));
    }

    public ItemQuote decode(byte[] packet)
    {
        Stream payload = new MemoryStream(packet, 0, packet.Length, false);
        return decode(payload);
    }
}

在解码器处,传入的流被解码以形成可读的结果。不幸的是,错误发生在:

price = encoding.GetString(ItemQuoteFramer.nextToken(wire, newline));

附留言:

An exception of type 'System.ArgumentNullException' occurred in mscorlib.dll but was not handled in user code

Additional information: Array cannot be null.

ItemQuoteFramer:

    public class ItemQuoteFramer
{
    public static byte[] nextToken(Stream input, byte[] delimiter)
    {
        int nextByte;

        //If the stream has already ended, return null
        if ((nextByte = input.ReadByte()) == -1)
            return null;

        MemoryStream tokenBuffer = new MemoryStream();
        do
        {
            tokenBuffer.WriteByte((byte)nextByte);
            byte[] currentToken = tokenBuffer.ToArray();
            if (endsWith(currentToken, delimiter))
            {
                int tokenLength = currentToken.Length - delimiter.Length;
                byte[] token = new byte[tokenLength];
                Array.Copy(currentToken, 0, token, 0, tokenLength);

                return token;
            }
        }
        while ((nextByte = input.ReadByte()) != -1);

        return tokenBuffer.ToArray();
    }

    static bool endsWith(byte[] value, byte[] suffix)
    {
        if (value.Length < suffix.Length)
            return false;

        for (int offset = 1; offset <= suffix.Length; offset++)
            if (value[value.Length - offset] != suffix[suffix.Length - offset])
                return false;

        return true;
    }
}

将在ItemQuoteDecoderText 中的变量"quant" 被填充后跳过它的定界符。发送数据包的最后一部分:“1000 12999 d”在 "quant" 中作为一个整体,最后两个 ("price" & "flags") 变量将 return 为空.

    public class SendUdp
{
    public SendUdp(string[] args)
    {
        SendUdpMethod(args);
    }

    void SendUdpMethod(string[] args)
    {
        //Check for correct amount of arguments
        if ((args.Length < 2) || (args.Length > 3))
            throw new ArgumentException("Parameters: <Destination> <Port> [<Encoding>]");

        string server = args[0];
        int destPort = Int32.Parse(args[1]);

        //Make an item to quote
        ItemQuote quote = new ItemQuote(12345678909876554L, "5mm Super Widgets", 1000, 12999, true, false);

        UdpClient client = new UdpClient();

        ItemQuoteEncoder encoder = ((args.Length == 3) ? new ItemQuoteEncoderText(args[2]) : new ItemQuoteEncoderText());
        byte[] codedQuote = encoder.encode(quote);

        client.Send(codedQuote, codedQuote.Length, server, destPort);
        client.Close();
    }
}

这是处理数据包接收方式的代码:

    public class ReceiveUdp
{
    public ReceiveUdp(string[] args)
    {
        ReceiveUdpMethod(args);
    }

    void ReceiveUdpMethod(string[] args)
    {
        //Check for correct amount of arguments
        if ((args.Length < 1) || (args.Length > 2))
            throw new ArgumentException("Parameters: <Port> [<Encoding>]");

        int port = Int32.Parse(args[0]);
        UdpClient client = new UdpClient(port);

        byte[] packet = new byte[ItemQuoteTextConst.MAX_WIRE_LENGTH];
        IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, port);

        packet = client.Receive(ref remoteIPEndPoint);
        ItemQuoteDecoderText decoder = ((args.Length == 2) ? new ItemQuoteDecoderText(args[1]) : new ItemQuoteDecoderText());

        ItemQuote quote = decoder.decode(packet);
        Console.WriteLine(quote);

        client.Close();
    }
}

ItemQuoteFramer 喜欢跳过定界符,我认为这就是问题所在。但我不知道该怎么办。有人愿意花时间帮我解决这个问题吗?

非常感谢,
法克拉达

答案在于分隔符的给出方式。变量 "quant" 包含(在发生错误时)以下内容:“1000 12999 d”。

如果您查看给出的定界符,它会给出:"newline"。如果我们将其更改为:"space",我们就解决了问题。

为了澄清,ItemQuoteDecoderText 中的以下内容:

    itemNo = encoding.GetString(ItemQuoteFramer.nextToken(wire, space));
    description = encoding.GetString(ItemQuoteFramer.nextToken(wire, newline));
    quant = encoding.GetString(ItemQuoteFramer.nextToken(wire, newline));
    price = encoding.GetString(ItemQuoteFramer.nextToken(wire, newline));
    flags = encoding.GetString(ItemQuoteFramer.nextToken(wire, newline));

应该变成:

    itemNo = encoding.GetString(ItemQuoteFramer.nextToken(wire, space));
    description = encoding.GetString(ItemQuoteFramer.nextToken(wire, newline));
    quant = encoding.GetString(ItemQuoteFramer.nextToken(wire, space));
    price = encoding.GetString(ItemQuoteFramer.nextToken(wire, space));
    flags = encoding.GetString(ItemQuoteFramer.nextToken(wire, newline));

感谢所有花时间看这篇文章的人。

非常感谢,
法克拉达