TCP тыңдаушыны парам ретінде объектімен жазу

Мен нысанды TCP қосылымы арқылы C# түрінде жіберу әдісін түсінемін; Мен StreamWriter пайдаланамын.

Бұл нысанды екінші жағынан қалай аламын?

Мен StreamReader қолданамын, бірақ ол object түрінің параметрін қамтымайды.

Мұны қалай жасауға болады?

0
Serialization , XmlSerializer BinaryFormatter SoapFormatter DataContractSerializer туралы JavaScriptSerializer және т.б.
қосылды автор L.B, көзі
StreamReader/Writer мәтінге арналған. Мәтін жазбасаңыз, неге мәтінді жазасыз?
қосылды автор harold, көзі
Міне, мен не істегім келеді: Суреттер жиынтығын жібергім келеді: Image [] ImgArr = new ImgArr [2]; объект Obj = (нысан) ImgArr; Мен «Obj» -ді жіберіп, клиент жағынан ішкі суреттерді пайдалану үшін басқа зат ретінде алайын деп ...
қосылды автор YMELS, көзі
Барлығыңызға рахмет ...
қосылды автор YMELS, көзі
Мен екі сурет үшін 2 массив байтты қамтитын массивтерді серияладым, ол жұмыс істеді және екі кескінді сәтті алдым, бірақ арнасы өте баяу ...
қосылды автор YMELS, көзі

3 жауаптар

IMO ең жақсы шешім - ағыннан оқу үшін BinaryReader пайдалану. Сонымен қатар, ағынды BinaryWriter класының көмегімен жазыңыз.

Егер сіздің нысаныңыз негізгі түрлердің біреуі болмаса, TCP қосылымы арқылы жіберу алдында сериялауға тура келеді.

1
қосылды
Сіз BinaryFormatter көмегімен объектіңізді сериялауыңыз керек және оны басқа жағынан босатасыз: msdn.microsoft.com/en-us/library/…
қосылды автор Wojteq, көзі
Міне, мен не істегім келеді: Суреттер жиынтығын жібергім келеді: Image [] ImgArr = new ImgArr [2]; объект Obj = (нысан) ImgArr; Мен «Obj» -ді жіберіп, клиент жағынан ішкі суреттерді пайдалану үшін басқа зат ретінде алайын деп ...
қосылды автор YMELS, көзі

ProtoBuf арқылы өзіңіздің жіберетін объектілеріңізді/байттарыңыздан түрлендіруге кеңес беремін желіде (яғни, сериализациялау). Бұл екілік екілік сериализаторларға (жылдамдық, нұсқалар) қарағанда әлдеқайда жақсы.

Сондай-ақ, жазылған деректерге ұзындық/өлшемдік префиксті қосу үшін достық көмекшілер бар, бұл сізге қабылдаушы жағынан деректерді оқып білу үшін пайдалы.

Төменде байланыс орнатылып болғаннан кейін, мен сериялық және желілік байланыс жасау үшін қолданған көмекші сынып болды:

public class Messenger
{
    private readonly TcpClient client;

    private readonly NetworkStream stream;

    public IPEndPoint RemoteEndPoint { get { return (IPEndPoint) client.Client.RemoteEndPoint; } }

    public Messenger( TcpClient client )
    {
        this.client = client;
        stream = client.GetStream();
    }

    #region Send and Receive
    public TResponse SendReceive<trequest, TResponse>( TRequest request ) where TRequest : Message where TResponse : Message
    {
        Send( request );
        return Receive<tresponse>();
    }

    public void Send<trequest>( TRequest request ) where TRequest : Message
    {
        using( var ms = new MemoryStream())
        {
            Serializer.SerializeWithLengthPrefix( ms, request, PrefixStyle.Fixed32 );
            stream.Write( ms.GetBuffer(), 0, (int) ms.Length );
            stream.Flush();
        }
    }

    public TResponse Receive<tresponse>() where TResponse : Message
    {
        try
        {
            return GetMessage<tresponse>();
        }
        catch (Exception ex)
        {
            if (ex is IOException || ex is InvalidOperationException)
            {
                stream.Dispose();
            }
            throw;
        }
    }
    #endregion

    #region Helpers
    private TMessage GetMessage() where TMessage : Message
    {
        int messageLength = BitConverter.ToInt32(GetBytes(stream, 4), 0);
        byte[] data = GetBytes(stream, messageLength);
        using (var ms = new MemoryStream(data))
        {
            return Serializer.Deserialize(ms);
        }
    }

    private static byte[] GetBytes(NetworkStream stream, int length)
    {
        int bytesRequired = length;
        int bytesRead = 0;
        var bytes = new byte[length];
        do
        {
            while( !stream.DataAvailable )
                Thread.Sleep( 100 );                    
            int read = stream.Read(bytes, bytesRead, bytesRequired);
            bytesRequired -= read;
            bytesRead += read;
        }
        while (bytesRequired > 0);
        return bytes;
    }
    #endregion
}

Ескерту: Serializer классы ProtoBuf кітапханасынан.

0
қосылды
Содан кейін Суреттер сипаты бар класс жасаңыз (Сурет түрі []), оны қажетті ProtoBuf атрибуттарымен безендіріңіз (бұл туралы анықтама үшін құжаттарды оқыңыз немесе StackOverflow іздеу) және оны жіберу үшін Send әдісін пайдаланыңыз (және Receive on алушы тарап, анық).
қосылды автор Morten Mertner, көзі
Міне, мен не істегім келеді: Суреттер жиынтығын жібергім келеді: Image [] ImgArr = new ImgArr [2]; объект Obj = (нысан) ImgArr; Мен «Obj» -ді жіберіп, клиент жағынан ішкі суреттерді пайдалану үшін басқа зат ретінде алайын деп ...
қосылды автор YMELS, көзі

BinaryFormatter , сіз сіздің yoursekf нысанын босатуыңыз керек

Binary Formatter үшін msdn ішінен өзгертілген мысал:

Сіз үлгі болдыңыз дейік:

[Serializable] //you could also make the class implement ISerializable
class SomeModel
{
    public String Name
    {
        get;
        set;
    }
}

сізде NetworkStream бар:

NetworkStream ns;

серияландыру бөлігін қалай жасауға болатының негізгі мысалы:

void Serialize() 
{
    SomeModel myModel = new SomeModel()
    {
        Name = "mooo"
    };

   //Construct a BinaryFormatter and use it to serialize the data to the stream.
    BinaryFormatter formatter = new BinaryFormatter();
    try 
    {
        formatter.Serialize(ns, myModel);
    }
    catch (SerializationException e) 
    {
        throw e;
    }
}

және десеряциялауға қатысты

void Deserialize() 
{
    SomeModel myModel;
    try 
    {
        BinaryFormatter formatter = new BinaryFormatter();

       //Deserialize the object from the stream and 
       //assign the reference to the local variable.
        myModel = (SomeModel) formatter.Deserialize(ns);
    }
    catch (SerializationException e) 
    {
        throw e;
    }
}

Сізге күтім жасау керек нәрсе бар. Сіз босатылған кезде білуіңіз керек, сіз оны ағызып, бірдеңе алып кете алмайсыз, сіз оқып отырған нәрсе шын мәнінде кейбір Кейбір моделі-сыныпты білетін боласыз. Мен сіздің кодыңыздың қалай көрінетінін білмеймін, сондықтан бұл мәселе бар ма, жоқ па, соны білмеймін.

Қалай болса да, сіздің екінші таңдауыңыз BinaryReader пайдалану болады. Сізге өзіңіздің данаңызды жасауыңыз керек және деректерді қолмен оқуыңыз керек.

using(BinaryWriter writer =
    new BinaryWriter(ns))
{
    binWriter.Write(myModel.Name);
}

оқу:

 using(BinaryReader reader =
        new BinaryReader(ns))
 {
    try
    {
        SomeModel myModel = new SomeModel();

        myModel.Name = binReader.ReadString();
    }

   //If the end of the stream is reached before reading
   //the four data values, ignore the error and use the
   //default settings for the remaining values.
    catch(EndOfStreamException e)
    {
        Console.WriteLine("{0} caught and ignored. " +
            "Using default values.", e.GetType().Name);
    }
}
0
қосылды
Міне, мен не істегім келеді: Суреттер жиынтығын жібергім келеді: Image [] ImgArr = new ImgArr [2]; объект Obj = (нысан) ImgArr; Мен «Obj» -ді жіберіп, клиент жағынан ішкі суреттерді пайдалану үшін басқа зат ретінде алайын деп ...
қосылды автор YMELS, көзі