Problemi con i sockets

venerdì 07 maggio 2004 - 12.27

shaolin Profilo | Newbie

Ciao a tutti.
Io mi collego ad un server (porta 21) tramite i socket.
All'inizio, dopo la connessione vado a leggere la risposta del server,
solo che ottengo un risultato anomalo.
Premetto che il server mi dovrebbe restituire questo:

220-QTCP at INTRANET.XXXXX.IT.
220 Connection will close if idle more than 5 minutes.

mentre io ottengo solo:

220-QTCP at INTRANET.XXXXX.IT.

La cosa strana è che se eseguo passo-passo la receive mi torna le due
righe! Ho provato prima della receive a mettere un DoEvents(), ma non è
servito :(

Perchè si comporta così?

Posto un po' di codice...

' CONNESSIONE AL SOCKET

Public Sub Connetti(ByVal ind As String, ByVal port As Int32)
mysock = New Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp)
Dim ipadd As IPAddress = Dns.Resolve(ind).AddressList(0)
Dim x As New Net.IPEndPoint(ipadd, port)
If Not mysock.Connected Then
mysock.Connect(x)
End If
End Sub

' RICEZIONE
Public Function RispostaServer() As String
Dim dati(255) As Byte

Application.DoEvents()
mysock.Receive(dati)
Return Encoding.ASCII.GetString(dati)
End Function

' Ho anche modificato la funzione in questo modo ma non risolvo il problema:

Public Function RispostaServer() As String
Dim dati(255) As Byte
Dim str As String = ""
Dim ricevuti As Int32
Application.DoEvents()
mysock.Receive(dati, dati.Length, SocketFlags.None)
ricevuti = mysock.Available()
str = Encoding.ASCII.GetString(dati)
While ricevuti > 0
Application.DoEvents()
mysock.Receive(dati, dati.Length, SocketFlags.Partial)
str += Encoding.ASCII.GetString(dati)
ricevuti = mysock.Available()
End While
RaiseEvent InfoDialogo(Encoding.ASCII.GetString(dati))
Return Encoding.ASCII.GetString(dati)
End Function



Ringrazio in anticipo chi mi aiuterà :)

Max

Brainkiller Profilo | Guru

Ciao,
il server a cui ti stai connettendo di che tipo è ? E' un server particolare come POP3 SMTP o simili ?

La conosci la differenza fra socket sincroni e asincroni ?

ciao
david

shaolin Profilo | Newbie

Il server è FTP.
Vorrei fare un client ftp.
Si, la classe socket implementa anche questo... Il tuo è per caso uno spunto?

Max

Brainkiller Profilo | Guru

Eh eh, allora ti consiglio di leggerti bene le RFC sull'FTP:
http://www.ietf.org/rfc/rfc0959.txt

L'FTP è il protocollo più ostico e difficile da implementare tanto che tempo fa ho abbandonato il tentativo di costruzione di un client FTP, perchè in pratica tu fai una richiesta al Server di porta disponibile, lui ti da' la porta e tu ti devi connettere parallelamente su quella porta per ricvere i dati e così per ogni richiesta, se vuoi ricevere file, elencare le cartelle, ecc. ecc. e' veramente molto incasinato. Se però ci riesci fammi sapere.

ciao
david

shaolin Profilo | Newbie

Ciao!
Guarda, poco più di un anno fa mi ero messo a studiare il vb.net e ho scelto di fare un client ftp apposito per i server as400.
Avevo già impostato le classi necessarie e avevo aggirato i problemi che ho adesso al 90%.
Solo che la soluzione trovata non era pulita come vorrei ora che fosse. Purtroppo poi ho abbandonato il progetto e non riesco più a trovare il cd dove ho copiato tutti i file :(
Il problema che non riesco proprio a capire è come mai questi dannati socket (la classe del framework) in modalità passo-passo mi ritornano perfettamente le risposte dei server, a runtime normale quasi sempre mi tornano solo parte della risposta... Visto che ho la ver 1.0 ho pensato di applicare la 1.1 del framework e vedere se serve a qualcosa (come si dice: la speranza è l'ultima a morire)... Prima di cambiare metodo (vedrò magari la classe TCPclient) preferirei trovare questa soluzione...
Ti farò sapere se ho sviluppi...

Grazie e ciao

Max

Brainkiller Profilo | Guru

La classe TcpClient ti sconsiglio di utilizzarla, io mi sono trovato male, utilizza piuttosto la Socket pura.
Riguardo il Debug, allora sono due cose diverse. Se tu vai in debug e fai passo passo quando chiami la Receive lui si ferma e quindi può ricevere tutti i dati, se fai a runtime invece il tutto viene eseguito alla velocità della luce e quindi è possibile che la linea Internet sia più lenta dell'elaboratore e quindi succede che ti arriva solo alcuni pacchetti di dati e non tutti. In quetso caso allora devi chiamare una seconda volta la receive fino a quando sai che tutti i dati sono arrivati. Prova vedrai che funziona, chiama la receive due volte consecutivamente.

ciao
david

shaolin Profilo | Newbie

Purtroppo se seguo il tuo suggerimento incorro nel problema che se il server non ha più niente da mandarmi resta bloccato in attesa, pur ammettendo che è vero ciò che dici sul tempo lampo dell'esecuzione.
La soluzione che a occhio parrebbe più giusta, ma ancora non funziona, è quella di un ciclo dove loopo finchè non arrivo a zero con i bytes ricevuti dal server... Tuttavia, come dicevo, non funziona ancora perchè mi perde i pezzi, nonostante il decremento dei byte letti avvenga...
Se fosse come dici tu questa routine dovrebbe funzionare , e invece no :(
Ecco il codice:

Public Function RispostaServer() As String
Dim dati(255) As Byte
Dim str As String = ""
Dim ricevuti As Int32 = 1

Do While ricevuti <> 0
ricevuti = mysock.Receive(dati, dati.Length, SocketFlags.None)
str = str + Encoding.ASCII.GetString(dati, 0, ricevuti)
ricevuti = mysock.Available
Loop
RaiseEvent InfoDialogo(str)
Return str
End Function


Ps: se vuoi posso postare il programma zippato che ho fatto finora così lo puoi provare...

Grazie
Max

Brainkiller Profilo | Guru

Ciao, se non sbaglio tu qui stai usando dei Socket sincroni o blocking.
Infatti se chiami la receive e il server non ti manda più dati il tuo client resta bloccato in attesa (è il client che resta bloccato non il server).
Se tu leggessi le RFC del FTP dovresti apprendere che quando il server manda i messaggi questi sono sempre terminati da un \r\n cioè carriage return + new line, quindi tu quandi codifichi i byte ricevuti con GetString potresti concatenarli una stringa e potresti controllare ogni volta se i due caratteri finali sono \r\n se così fosse significa che il server ha terminato di spedirti i bytes e quindi a questo punto è il tuo turno e puoi mandargli dei comandi di autenticazione per esempio.

Sicuramente in questo caso credo che lavorare con sockets asincroni sia la migliore soluzione.

ciao
david

shaolin Profilo | Newbie

L'rfc l'avevo letta bene l'anno scorso e avevo capito che il messaggio "finale" era dato da una linea con 3 numeri seguita da uno spazio.
I server ftp quando mandano commenti lo fanno con 3 numero seguiti da un "-".
Ad ogni modo ho trovato il vecchio codice e come avevo risolto. Il metodo è molto maccheronico ma funzionava... Domattina magari posto il codice...

Buonanotte :)

Max
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2023
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5