Avatar billede mr-kill Nybegynder
04. november 2008 - 21:04 Der er 16 kommentarer og
1 løsning

Problemer med socket

Jeg har lavet et program der skal sende nolge objecter til et andet program.

Derfor bruger jeg Serialize på de objecter der skal sendes og åbner en socket.
Jeg laver så hver object om til en "pakke" der ser ud på denne måde:
[1 byte ] - typen af object
[3 bytes] - længede på object
[X bytes] - object

det hele sender jeg så med socket_name.Send(MyBytes)

programmet i den anden ende henter så pakken på denne måde:
Hent de første 4 bytes
find type ved hjælpe af første byte
find længde ved hjælp af de 3 næste bytes
Hent [længde] antal bytes og lav dem til et object

Det plejer at køre fint, men nogen gange er det som om at ikke alle bytes når frem. Jeg får nogen gange 255 i første byte og jeg har kun 13 forskellige pakke typer. Det er forskelligt hvilket pakke der fejler og nogen gange fejler ingen.

Grunden må vel være at nogen pakker smelter sammen, forstår bare ikke hvordan det kan ske?

Serveren kører hver client i en tråd for sig selv og jeg er rimlig sikker på at problemet ligger i modtagelsen.

Nogen idéer?
Avatar billede arne_v Ekspert
04. november 2008 - 21:09 #1
Husker du at læse i en while løkke ?
Avatar billede mr-kill Nybegynder
04. november 2008 - 21:38 #2
Jep :)
Avatar billede arne_v Ekspert
05. november 2008 - 01:27 #3
Må vi se noget kode ?
Avatar billede mr-kill Nybegynder
05. november 2008 - 13:00 #4
Har en klasse kladet Packet den indeholder:
enum NetworkTypes
NetworkTypes type;
byte[] data;
public byte[] GetBytes()
{
    byte[] toSend = new byte[data.Length + 4];

    toSend[0] = (byte)type;
    SizeToByte(data.Length).CopyTo(toSend, 1);
    data.CopyTo(toSend, 4);
   
    return toSend;
}
public static byte[] SizeToByte(int size)
{
    return new byte[] {
        (byte)((int)size & 255),
        (byte)(((int)size >> 8) & 255),
        (byte)(((int)size >> 16) & 255)
  };
}
public static int SizeToInt(byte[] data, int startIndex)
{
    return ((int)data[startIndex + 2] << 16) + ((int)data[startIndex + 1] << 8) + (int)data[startIndex];
}


Har så en metode til at sende en pakke:
public bool Send(Packet packet)
{
    try
    {
        byte[] bytesToSend = packet.GetBytes();
        clientSocket.SendBufferSize = bytesToSend.Length;
        clientSocket.Send(bytesToSend);
    }
    catch (SocketException)
    {
        return false;
    }

    return true;
}


Og modtage:
public static bool RecivePacket(Socket s, out NetworkTypes type, out byte[] data)
{
    byte[] header;
    int dataSize;

    try
    {
        header = new byte[4];
        s.ReceiveBufferSize = 4;
        s.Receive(header);
        type = (Packet.NetworkTypes)header[0];
        dataSize = Packet.SizeToInt(header, 1);
    }
    catch (SocketException)
    {
        type = NetworkTypes.Error;
        data = new byte[0];

        return false;
    }

    try
    {
        if (dataSize > 0)
        {
            data = new byte[dataSize];
            s.ReceiveBufferSize = dataSize;
            s.Receive(data);
        }
        else
            data = new byte[0];

        return true;
    }
    catch (SocketException)
    {
        data = new byte[0];

        return false;
    }
}
Avatar billede rasmuzzen Nybegynder
05. november 2008 - 16:25 #5
Jeg prøvede noget ligende, at sende et lille pladecover jpg billede på en 5 kb.

I ca. hver 20 testsending kom billedet kun halvt frem, eller med fejl. Så hvis jeg var dig ville jeg lave checksum og gensend ved fejl checksum.

Kender intet til denne ustabilitet.

MVH
Avatar billede mr-kill Nybegynder
05. november 2008 - 16:44 #6
Jah det r også noget alla det jeg får. Jeg kunne self. ta checksum og gensende ved fejl, men vil gerne vide hvorfor det går galt? jeg troede at TCP protokollen sikrede at mine pakker kom frem?
Avatar billede arne_v Ekspert
06. november 2008 - 05:23 #7
if (dataSize > 0)
        {
            data = new byte[dataSize];
            s.ReceiveBufferSize = dataSize;
            s.Receive(data);
        }

ligner ikke en while løkke !
Avatar billede arne_v Ekspert
06. november 2008 - 05:27 #8
if (dataSize > 0)
        {
            data = new byte[dataSize];
            s.ReceiveBufferSize = dataSize;
            int readSoFar = 0;
            while(readSoFar < dataSize)
            {
                readSoFar += s.Receive(data, readSoFar, dataSize - readSoFar, SocketFlags.None);
            }
        }
Avatar billede rasmuzzen Nybegynder
06. november 2008 - 10:04 #9
arne v. Er det ikke noget du har oplevet.

Jeg ved selvfølgelig ikke hvor mange programmer du har kørende "live" med sockets.

Af et eller andet dokument, jeg mindes engang at have læst om dig, kunne jeg se at du vist ikke har primær arbejde som programmør eller hvordan.

MVH
Avatar billede mr-kill Nybegynder
06. november 2008 - 11:17 #10
arne_v: troede godt man kunne læse det hele på en gang? Det kan man så ikke eller hvad?
Avatar billede mr-kill Nybegynder
06. november 2008 - 11:30 #11
Ser ud til at det virker bedre nu. Kan jeg godt sende uden at gøre det i en while ?
Avatar billede arne_v Ekspert
06. november 2008 - 13:02 #12
Når man læser fra en socket og skal læse N bytes skal man altid læse i en while løkke.

Man skal kun bruge en while løkke når man skriver til en socket hvis man er er i
non-blocking mode. Så du skulle være OK på det område.
Avatar billede mr-kill Nybegynder
06. november 2008 - 13:06 #13
Super. Jeg siger mange tak for hjælpen så :)

Læg et svar!
Avatar billede arne_v Ekspert
06. november 2008 - 13:11 #14
svar
Avatar billede arne_v Ekspert
06. november 2008 - 22:36 #15
rasmuzzen>

Nej - min erfaring er at TCP er reliable som den skal være.

Men den manglende while løkke i forbindelse med receive ses ofte. Det er ikke
specielt naturligt i mange situationer. Men har man haft problemet engang, så
husker man det fremover.
Avatar billede rasmuzzen Nybegynder
07. november 2008 - 08:45 #16
Ok, og jeg gætter på at de fleste eksempler fra eks. MOC kurser ikke har den, det er ligesom det det hele starter for mange af os.

MVH
Avatar billede arne_v Ekspert
08. november 2008 - 03:09 #17
Muligt.

Men derfor er problemet alligevel velkendt. Ikke kun i .NET - det ses også i C, Python etc..
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
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

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