我需要你的帮助、意见和正确的方法来完成我的项目(服务器客户端,但我一直停留在数据对话和通用类型中)

本文关键字:一直 客户端 服务器 停留在 数据 类型 对话 我的 帮助 需要你 要你的 | 更新日期: 2023-09-27 18:25:55

好吧,这会很长。

首先,我想向你介绍我确实需要什么:

我需要建议,你的意见,正确的方法背后的服务器客户端数据发送&接收(如果我在某个时候错了)

需要修复我卡住的地方(我已经指出了)

首先,我制作了一个类,它实际上是一个用于发送&接收数据。我的意思是有这样的方法:

void Write(byte arg)
void Write(ushort arg)
void Write(DateTime arg)
void Write(DateTime[] arg)
byte ReadByte()
int[] ReadIntArray(int count)

等等。等等。这种方法实际上向CCD_ 1写入字节。还有一些方法,比如Send()通过流发送数据,Clear()清除缓冲区。

public void Clear()
{
    motherBuffer.Clear();
}
public void Send()
{
    Stream.Write(motherBuffer.ToArray(), 0, motherBuffer.Count);
}

首先,我班的逻辑是这样的:

    public void Write(byte arg)
    {
        motherBuffer.Add(arg)
    }
    public void Write(short arg)
    {
        foreach (byte b in BitConverter.GetBytes(arg)) // calls Write(byte) twice
           Write(b);
    }
    public byte ReadByte()
    {
        if (!IsDataAvailable())
            throw new Exception("No-data is available to be read.");
        else
            return (byte)Stream.ReadByte();
    }
    public short ReadShort()
    {
        return BitConverter.ToInt16(new byte[2] { ReadByte(), ReadByte() }, 0); // calls readbyte twice
    }
    public short[] ReadShortArray(int length)
    {
        short[] r = new short[length];
        for (int i = 0; i <= length - 1; i++)
            r[i] = ReadShort();
        return r;
    }

但在我发现有更好的方法后,我改变了这个方法,比如:

        public void Write(byte arg)
        {
            motherBuffer.Add(arg);
        }
        public void Write(byte[] arg)
        {
            motherBuffer.AddRange(arg);
        }
        public void Write(short arg)
        {
            Write(BitConverter.GetBytes(arg)); // this time only calls Write(byte[]) once
        }
        public byte ReadByte()
        {
            if (!IsDataAvailable())
                throw new Exception("No-data is available to be read.");
            else
            {
                int read = Stream.ReadByte();
                if (read < 0)
                    throw new Exception("End of stream -1");
                else
                    return (byte)read;
            }
        }
        public byte[] ReadByteArray(int count)
        {
            if (!IsDataAvailable())
                throw new Exception("No-data is available to be read.");
            else
            {
                byte[] read = new byte[count];
                int result = Stream.Read(read, 0, count);
                if (result <= 0)
                    throw new Exception("End of stream -1");
                else
                    return read;
            }
        }
        public short ReadShort()
        {
            return BitConverter.ToInt16(ReadByteArray(2), 0); // this time calls once too
        }
        public short[] ReadShortArray(int length)
        {
            short[] r = new short[length];
            for (int i = 0; i <= length - 1; i++)
                r[i] = ReadShort();
            return r;
        }

在这一切之后,我想我为什么不做这样的事情(我真的很难过,因为这是一条更短的路,也是我将要陷入困境的地方):

        public T Read<T>() where T : int // I don't actually know what 'where T : int' does just tried for 'return (int)-1;' 
        {
            if (!IsDataAvailable())
                throw new Exception("No-data is available to read.");
            if (typeof(T) == typeof(byte))
            {
                int read = Stream.ReadByte();
                if (read < 0)
                    return (int)-1; // STUCK HERE
                else
                    return read as T; // STUCK HERE
            }
            else
            {
                 // STUCK HERE : because I don't know how to return & convert type of 'T'
            }
        }
        public int ReadArray<T>(T[] buffer, int offset, int count)
        {
            if (!IsDataAvailable())
                throw new Exception("No-data is available to read.");
            if (typeof(T) == typeof(byte))
            {
                return Stream.Read(buffer as byte[], offset, count);
            }
            else
            {
                int m = 2; // multplier for example: this is short. I didn't figure out how to get it like sizeof(T)
                byte[] byteBuffer = new byte[count * m]; // because I have to read twice amount of byte
                ReadArray<byte>(byteBuffer, 0, byteBuffer.Length); 
                // I really don't know how could I use T with BitConverter.GetBytes( of T );
            }
        }

我需要你的帮助、意见和正确的方法来完成我的项目(服务器客户端,但我一直停留在数据对话和通用类型中)

不要使用泛型,在这种情况下它们是你的敌人。只需编写您想要的代码,然后继续前进。真正可以改进的是使用WCF或Remoting进行网络通信,而不是手动封送处理。

这是实现Read的一种方法:

public static T Read<T>(this Stream stream)
{
    object ret = null;
    if (typeof(T) == typeof(byte))
        ret = stream.ReadInt8();
    else if (typeof(T) == typeof(Int16))
        ret = stream.ReadInt16();
    else if (typeof(T) == typeof(Int32))
        ret = stream.ReadInt32();
    if (ret == null)
        throw new ArgumentException("Unable to read type - " + typeof(T));
    return (T)ret;
}
public int ReadArray<T>(this Stream stream, T[] buffer, int offset, int count)
{
    for (int i = offset; i< count; i++) buffer[i] = stream.Read<T>();
}

您可能想了解一下WCF,因为它已经比您所能更好地解决了这个问题,并且可以让您直接关注应用程序逻辑,而不必担心如何在层之间移动数据;这是我能找到的最短的WCF示例,希望它能帮助

我知道这篇文章已经发布一年了,但我认为它值得添加到.

好吧,首先,正如几乎所有人都说的那样,使用WCF或其他已经实现并测试过的系统在层之间进行通信。

但要填补你的空白:

where T : int是一个通用约束,表示您将只返回一个int。如果int被替换为类似Stream的类,那么您是在说您将只返回Stream或从Stream派生的类。

因为您有一个int的通用约束,所以typeof(T)永远不会等于List<byte> motherBuffer0。

as运算符只能用于类而不能用于结构。由于int的一般约束,Tstruct

我可以告诉您,要解决return (int)-1;的问题,您需要先转换为object,然后再转换为T,就像return (T)(object)-1;一样。但我真的无法解释为什么,因为我还没有完全理解这一点。我可以为你指出Generics中的协方差和逆变换的方向http://msdn.microsoft.com/en-us/library/dd799517.aspx.

我希望你觉得这很有帮助。