Perdita di byte casuale durante lo streaming dei dati sulla rete
-
20-12-2019 - |
Domanda
Il mio problema è che quando sto streamando un flusso continuo di dati su una rete LAN locale a volte i byte casuali vengono persi nel processo.
Come è in questo momento il codice è impostato per flussi circa 1027 byte o così ~ 40 volte un secondo su una LAN e talvolta (molto raro) uno o più dei byte sono persi.
La cosa che mi sfoglia è che il byte effettivo non è "perso" è solo impostato su 0 indipendentemente dai dati originali.(Sto usando TCP a proposito)
Ecco il codice di invio:
public void Send(byte[] data)
{
if (!server)
{
if (CheckConnection(serv))
{
serv.Send(BitConverter.GetBytes(data.Length));
serv.Receive(new byte[1]);
serv.Send(data);
serv.Receive(new byte[1]);
}
}
}
.
e il codice ricevente:
public byte[] Receive()
{
if (!server)
{
if (CheckConnection(serv))
{
byte[] TMP = new byte[4];
serv.Receive(TMP);
TMP = new byte[BitConverter.ToInt32(TMP, 0)];
serv.Send(new byte[1]);
serv.Receive(TMP);
serv.Send(new byte[1]);
return TMP;
}
else return null;
}
else return null;
}
.
L'invio e la ricezione dei byte vuoti sono solo per mantenere il sistema in sincronizzazione. Personalmente penso che il problema sia sul lato ricevente del sistema.non sono stato in grado di dimostrare quel jet però.
Soluzione
Solo perché dai Receive(TMP)
un array di 4 byte non significa che riempirà quella matrice con 4 byte. La chiamata di ricezione è autorizzata a inserire ovunque tra 1
e byte TMP.Length
nell'array. È necessario controllare il int
restituito per vedere quanti byte dell'array si riempiono.
Le connessioni di rete sono basate su flusso non basate sul messaggio. Qualsiasi byte che hai indossato al filo si è concatenato in una grande coda e si legge dall'altra parte mentre diventa disponibile. Quindi, se hai inviato i due array 1,1,1,1
e 2,2,2,2
è del tutto possibile che sul lato ricevente chiami Receive
tre volte con un array a 4 byte e ottenere
- .
-
1,1,0,0
(ricevi2
restituito) -
1,1,2,2
(ricevi4
restituito) -
2,2,0,0
(ricevi2
restituito)
Allora, quindi cosa devi fare è guardare i valori che hai tornato da Receive
e tenere il looping fino a quando il tuo array di byte è pieno.
byte[] TMP = new byte[4];
//loop till all 4 bytes are read
int offset = 0;
while(offset < TMP.Length)
{
offset += serv.Receive(TMP, offset, TMP.Length - offset, SocketFlags.None);
}
TMP = new byte[BitConverter.ToInt32(TMP, 0)];
//I don't understand why you are doing this, it is not necessary.
serv.Send(new byte[1]);
//Reset the offset then loop till TMP.Length bytes are read.
offset = 0;
while(offset < TMP.Length)
{
offset += serv.Receive(TMP, offset, TMP.Length - offset, SocketFlags.None);
}
//I don't understand why you are doing this, it is not necessary.
serv.Send(new byte[1]);
return TMP;
.
Infine hai detto "Il flusso di rete ti confonde", sono disposto a scommettere il problema di cui sopra è una delle cose che ti ha confuso, andare a un livello inferiore non rimuovere quelle complessità. Se vuoi che queste parti complesse sono andate così che non devi gestirle, dovrai utilizzare una biblioteca di terze parti che lo gestirà per te all'interno della libreria.