Avatar billede deamill Nybegynder
02. september 2011 - 11:34 Der er 10 kommentarer og
1 løsning

Overføre en hel struct med winsocket?

Hej,

Jeg roder lidt med noget socket programmering i VB2010.

I den forbindelse tænkte jeg på om det er muligt at sende en user defined struct direkte via socket, altså forudsat at structen er kendt hos både client og server?

Kan man det, eller kan man kune sende "flad" tekst?

På forhånd tak.

Mvh.
Kenneth
Avatar billede arne_v Ekspert
02. september 2011 - 15:27 #1
Det kan du godt.

BinaryFormatter kan serialisere og deserialisere et objekt (forudsat at det er serializable!) til og fra en socket stream.
Avatar billede deamill Nybegynder
03. september 2011 - 10:51 #2
Vil det sige jeg skal implementere serialize i mit objekt, som så serializer til en fil, og så læser jeg vilen og sender med socket?

Eller kan man serialize direkte til en socket?

Har kigget på den her kode:
Sub Serialize()

        ' Create a hashtable of values that will eventually be serialized.
        Dim addresses As New Hashtable
        addresses.Add("Jeff", "123 Main Street, Redmond, WA 98052")
        addresses.Add("Fred", "987 Pine Road, Phila., PA 19116")
        addresses.Add("Mary", "PO Box 112233, Palo Alto, CA 94301")

        ' To serialize the hashtable (and its key/value pairs), 
        ' you must first open a stream for writing.
        ' In this case, use a file stream.
        Dim fs As New FileStream("DataFile.dat", FileMode.Create)

        ' Construct a BinaryFormatter and use it to serialize the data to the stream.
        Dim formatter As New BinaryFormatter
        Try
            formatter.Serialize(fs, addresses)
        Catch e As SerializationException
            Console.WriteLine("Failed to serialize. Reason: " & e.Message)
            Throw
        Finally
            fs.Close()
        End Try
    End Sub



    Sub Deserialize()
        ' Declare the hashtable reference.
        Dim addresses As Hashtable = Nothing

        ' Open the file containing the data that you want to deserialize.
        Dim fs As New FileStream("DataFile.dat", FileMode.Open)
        Try
            Dim formatter As New BinaryFormatter

            ' Deserialize the hashtable from the file and
            ' assign the reference to the local variable.
            addresses = DirectCast(formatter.Deserialize(fs), Hashtable)
        Catch e As SerializationException
            Console.WriteLine("Failed to deserialize. Reason: " & e.Message)
            Throw
        Finally
            fs.Close()
        End Try

        ' To prove that the table deserialized correctly,
        ' display the key/value pairs.
        Dim de As DictionaryEntry
        For Each de In addresses
            Console.WriteLine("{0} lives at {1}.", de.Key, de.Value)
        Next
    End Sub
End Module


Elller er det noget helt andet du mener?

/Kenneth
Avatar billede arne_v Ekspert
03. september 2011 - 14:48 #3
Du behoever ikke nogen fil. Du kan serialisere direkte til din network stream.

Og du kan noejes med at saette serializable attribut paa klassen.
Avatar billede deamill Nybegynder
04. september 2011 - 17:42 #4
ok, kan du evt. kort fortælle hvordan jeg gør det, atlså laver en klasse med serializable attributten?

Skal jeg bruge Implements ... ?

/Kenneth
Avatar billede arne_v Ekspert
05. september 2011 - 01:49 #5
Eksempel:

C:\Work>type Data.vb
Imports System

<Serializable>
Public Class T1
    Private _f1 As Integer
    Private _f2 As String
    Public Overridable Property F1 As Integer
        Get
            return _f1
        End Get
        Set
            _f1 = Value
        End Set
    End Property
    Public Overridable Property F2 As String
        Get
            return _f2
        End Get
        Set
            _f2 = Value
        End Set
    End Property
End Class

C:\Work>vbc /t:library Data.vb
Microsoft (R) Visual Basic Compiler version 10.0.30319.225
Copyright (c) Microsoft Corporation.  All rights reserved.


C:\Work>type Server.vb
Imports System
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Imports System.Runtime.Serialization.Formatters.Binary

Public Class Server
    Public Shared Sub Main(args As String())
        Dim server As New TcpListener(IPAddress.Any, 12345)
        server.Start()
        Dim client As TcpClient = server.AcceptTcpClient()
                Dim binser As BinaryFormatter = New BinaryFormatter()
                Dim o As T1 = CType(binser.Deserialize(client.GetStream()), T1)
        client.Close()
        server.Stop()
        Console.WriteLine(o.F1 & " " & o.F2)
    End Sub
End Class


C:\Work>vbc /r:Data.dll Server.vb
Microsoft (R) Visual Basic Compiler version 10.0.30319.225
Copyright (c) Microsoft Corporation.  All rights reserved.


C:\Work>type Client.vb
Imports System
Imports System.IO
Imports System.Net.Sockets
Imports System.Runtime.Serialization.Formatters.Binary

Public Class Client
        Public Shared Sub Main(args As String())
                Dim o As T1 = New T1
                o.F1 = 123
                o.F2 = "ABC"
        Dim client As New TcpClient("localhost", 12345)
                Dim binser As BinaryFormatter = New BinaryFormatter()
                binser.Serialize(client.GetStream(), o)
        client.Close()
    End Sub
End Class


C:\Work>vbc /r:Data.dll Client.vb
Microsoft (R) Visual Basic Compiler version 10.0.30319.225
Copyright (c) Microsoft Corporation.  All rights reserved.
Avatar billede deamill Nybegynder
05. september 2011 - 07:11 #6
Ahh, nu er jeg med :-) Takker mange gange! Måske lige et tilægsspørgsmål.. Er der nogle regler min klasse skal overholde for at jeg kan sætte <Serializable> attrubutten?

P.S. Svar lige ;-)

/Kenneth
Avatar billede deamill Nybegynder
05. september 2011 - 09:53 #7
Prøvede lige at lave et client og et server program med din kode for at teste, og jeg får en fejl på serveren, når den modtager objektetk.

Fejlen:
Unable to find assembly 'ClientSerialsizable, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

I line (på server):
Dim o As T1 = CType(binser.Deserialize(client.GetStream()), T1)


/Kenneth



Server program:
Imports System
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Imports System.Runtime.Serialization.Formatters.Binary


Module Module1

    <Serializable()>
    Public Class T1
        Private _f1 As Integer
        Private _f2 As String
        Public Overridable Property F1 As Integer
            Get
                Return _f1
            End Get
            Set(ByVal value As Integer)
                _f1 = value
            End Set
        End Property
        Public Overridable Property F2 As String
            Get
                Return _f2
            End Get
            Set(ByVal value As String)
                _f2 = value
            End Set
        End Property
    End Class

    Sub Main()
        Dim server As New TcpListener(IPAddress.Any, 12345)
        server.Start()
        Dim client As TcpClient = server.AcceptTcpClient()
        Dim binser As BinaryFormatter = New BinaryFormatter()
        Dim o As T1 = CType(binser.Deserialize(client.GetStream()), T1)
        client.Close()
        server.Stop()
        Console.WriteLine(o.F1 & " " & o.F2)
    End Sub

End Module





****

Client program:
Imports System
Imports System.IO
Imports System.Net.Sockets
Imports System.Runtime.Serialization.Formatters.Binary


Module Module1

    <Serializable()>
    Public Class T1
        Private _f1 As Integer
        Private _f2 As String
        Public Overridable Property F1 As Integer
            Get
                Return _f1
            End Get
            Set(ByVal value As Integer)
                _f1 = value
            End Set
        End Property
        Public Overridable Property F2 As String
            Get
                Return _f2
            End Get
            Set(ByVal value As String)
                _f2 = value
            End Set
        End Property
    End Class

    Sub Main()
        Dim o As T1 = New T1
        o.F1 = 123
        o.F2 = "ABC"
        Dim client As New TcpClient("localhost", 12345)
        Dim binser As BinaryFormatter = New BinaryFormatter()
        binser.Serialize(client.GetStream(), o)
        While True
            'Test
        End While
        client.Close()
    End Sub

End Module
Avatar billede arne_v Ekspert
05. september 2011 - 16:01 #8
Jeg mener at de enkelte fields ogsaa skal vaere serializale (int, string, double etc. er serializable).
Avatar billede arne_v Ekspert
05. september 2011 - 16:03 #9
Det er meget vigtigt at bygger dine data klasser til en seperat DLL som saa bruges af baade client og server.

.NET leder efter kombinationen af fuld klassenavn og assemblyname (lidt mere kompliceret, men godt nok for denne diskussion).

Saa 3 projekter:
  data
  client
  server
Avatar billede arne_v Ekspert
05. september 2011 - 16:03 #10
og et svar
Avatar billede deamill Nybegynder
07. september 2011 - 20:27 #11
Ok, tak for svaret, jeg vil prøve :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester