Comunicazione tcp con pc remoto

mercoledì 24 febbraio 2010 - 10.26

basicdany Profilo | Expert

Ciao, a tutti, dovrei effettuare una connessione tcp con un pc remoto, la situazione e che ho un
pc server con ip 192.168.1.2 su porta 3058 e
pc client 192.168.1.88 su porta 61963

io dovrei essere il pc client 192.168.1.88 e dovrei ricevere i dati e rispondere con determinate stringhe che gia conosco.

n.b. il pc server ha un software che non ho sorgenti e un pacchetto chiuso, quindi non ho possibilita di capire come effettua la connessione.

Come effettuo questa connessione con il pc remoto tramite vb.net 2003 o 2005 0 2008, mi servirebbe anche qualche esempio di codice.

grazie a tutti.

luigidibiasi Profilo | Guru

>Ciao, a tutti, dovrei effettuare una connessione tcp con un pc
>remoto, la situazione e che ho un
>pc server con ip 192.168.1.2 su porta 3058 e
>pc client 192.168.1.88 su porta 61963
>
>io dovrei essere il pc client 192.168.1.88 e dovrei ricevere
>i dati e rispondere con determinate stringhe che gia conosco.
>
>n.b. il pc server ha un software che non ho sorgenti e un pacchetto
>chiuso, quindi non ho possibilita di capire come effettua la
>connessione.

>Come effettuo questa connessione con il pc remoto tramite vb.net
>2003 o 2005 0 2008, mi servirebbe anche qualche esempio di codice.

La connessione via tcp và stabilita tramite gli oggetti nel namespaces System.Net.Sockets (TcpClient o altri)
mi spiace non poter scrivere un esempio ma non ho vb sotto mano... prova a cercare su msdn
>
>grazie a tutti.

Luigi Di Biasi
http://blogs.dotnethell.it/luigidibiasi/
http://www.dibiasi.it/

basicdany Profilo | Expert

ciao, ho seguito il tuo consiglio, ho visto su msdn e ho visto come effettuare una connessione con i socket in tcp,
ho quindi realizzato un programmino che si mette in ascolto su una determinata porta,
lo quindi installato su un pc in rete e ho messo in ascolto su una determinata porta che utilizza questo server, non ricevo nessun dato!
tengo a precisare che il programmino da me realizzato con i socket se lo provo tra 2 pc in rete riesce tranquillamente a inviare stringa da un pc all'altro e viceversa. (come una chatt)
Mi chiedo dal lato server visto che non so cosa utilizza come componente per inviare i dati, i socket che sto utilizzando in .net possono essere non adatti a questo tipo di trasmissione, ho i socket di .net possono ricevere qualsiasi dato?


n.b. come spiegato all'inizio la connessione e del tipo tcp, quindi ho impostato il socket di .net per ricevere trasmissioni tcp, posto il codice, magari puo essere utile a qualcuno e puoi aiutarmi nel caso ho sbagliato qualcosa:

Private Sub CmdConnetti_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CmdConnetti.Click

Try
serversocket = New Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Dim myip As IPAddress = IPAddress.Parse(txtiplocale.Text)
Dim port As Integer = txtportaascolto.Text
Dim info As New IPEndPoint(myip, port)
serversocket.Bind(info)
serversocket.Listen(50)
Dim readthread As New Thread(New ThreadStart(AddressOf myread))
readthread.Start()
CmdConnetti.Text = "ok"
Catch ex As Exception
CmdConnetti.Text = "errore"
End Try

End Sub

procedura ricezione:

Private Sub myread()
Do While True
clientsocket = serversocket.Accept()
Dim bytes(1024) As Byte
Dim i As Integer = clientsocket.Receive(bytes, 0, clientsocket.Available, SocketFlags.None)
Dim msg As String = System.Text.Encoding.ASCII.GetString(bytes, 0, i)
'RaiseEvent updatetext(msg)
Me.SetText(msg)
Loop
End Sub


Spero qualcuno posso darmi una dritta, grazie a tutti.

luigidibiasi Profilo | Guru

>ciao, ho seguito il tuo consiglio, ho visto su msdn e ho visto
>come effettuare una connessione con i socket in tcp,
>ho quindi realizzato un programmino che si mette in ascolto su
>una determinata porta,

Ciao,
forse ho fatto un po di confusione io...
Mi era sembrato di capire che il tuo programma doveva collegarsi ad un server ma tu hai usato:

> Dim port As Integer = txtportaascolto.Text
> Dim info As New IPEndPoint(myip, port)
> serversocket.Bind(info)
> serversocket.Listen(50)

in questo modo tu metti in attesa il tuo PC sulla porta port e attendi che qualcuno si colleghi. (infatti dopo usi la accept)

Tu devi ricevere la connessione e poi ricevere i dati o devi effettuare la connessione e ricevere i dati?
(scusa il gioco di parole)

Luigi Di Biasi
http://blogs.dotnethell.it/luigidibiasi/
http://www.dibiasi.it/

basicdany Profilo | Expert

ciao, ti ringrazio sempre per il tuo aiuto molto prezioso,
io quello che sto cercando di fare e ricevere i dati e poi rispondere al server, come ti spiegavo e' un software installato di cui non ho il sorgente.
Vedo che sei esperto nell'uso dei socket,
ti chiedo una domanda importante, dall'altro lato e' importante che il programma che invia i pacchetti di rete usi la stessa tecnica e linguaggio che sto utilizzando io? se fosse cosi sto perdendo solo tempo perche' dall'altra parte e' un pacchetto chiuso, non so cosa utilizza per effettuare la trasmissione di rete, i mei elementi certi sono ip server e ip dove trasmette e le relative porte che apre per effettuare la comunicazione tcp.

grazie tanto

luigidibiasi Profilo | Guru

ciao e scusa per il ritardo ma non ricevevo più le notifiche dal sito ed avevo perso di vista il topic =)

>io quello che sto cercando di fare e ricevere i dati e poi rispondere
>al server, come ti spiegavo e' un software installato di cui
>non ho il sorgente.

Per collegarti al server devi usare l'oggetto TcpClient (http://msdn.microsoft.com/it-it/library/system.net.sockets.tcpclient(VS.80).aspx) e passargli l'IP e la porta dove sta girando il server.

>Vedo che sei esperto nell'uso dei socket,
>ti chiedo una domanda importante, dall'altro lato e' importante
>che il programma che invia i pacchetti di rete usi la stessa
>tecnica e linguaggio che sto utilizzando io?
no non è importante devi solo capire se usa TCP o UDP come protocollo...

Una cosa importante è che tu sappi la struttura del pacchetto che ricevi (se binario).
Nel caso i dati ti arrivano in formato testuale li ricevi con l'oggetto TcpClient tranquillamente

>>se fosse cosi sto
>perdendo solo tempo perche' dall'altra parte e' un pacchetto
>chiuso, non so cosa utilizza per effettuare la trasmissione di
>rete, i mei elementi certi sono ip server e ip dove trasmette
>e le relative porte che apre per effettuare la comunicazione
>tcp.
queste informazioni ti bastano per collegarti e per iniziare a ricevere i dati... (nel caso in cui il server li invii immediatamente appena ti connetti)

fai così ... utilizza start->esegui-> TELNET [IPSERVER] [PORTA] e vedi un pò cosa ricevi... se telnet non si collega e sei sicuro che il server sia attivo e che nessun firewall ti blocchi probabilmente utilizza UDP.
>
>grazie tanto
scusami tu per il ritardo
guardati l'esempi su tcpclient a questo indirizzo http://msdn.microsoft.com/it-it/library/system.net.sockets.tcpclient(VS.80).aspx
magari trovi tutto già pronto...


Luigi Di Biasi
http://blogs.dotnethell.it/luigidibiasi/
http://www.dibiasi.it/

basicdany Profilo | Expert

Con telnet il server è attivo. Mi chiedevo quando un client riparte o si accende cosa avviene per connettersi. Il server prova sempre a chiamarlo e quando il client è riacceso si riconnette?? o è il client che invia un comando alla porta del server il quale capisce che si è riacceso e risponde creando la connessione?? Nel primo caso il server dovrebbe sapere la porta di ricezione del client, cosa improbabile. Quindi devo supporre che sia il client che invia la chiamata al server indicando la porta di ricezione. Come viene determinata la porta di ricezione??? Se la porta di ricezione fosse fuori dalle standard come la definisco???

grazie tanto

luigidibiasi Profilo | Guru

>Con telnet il server è attivo.
ok

>Mi chiedevo quando un client riparte
>o si accende cosa avviene per connettersi.

Il client deve chiamare il server a meno che tu non scriva due peer che fanno sia client che server.

>Il server prova sempre
>a chiamarlo e quando il client è riacceso si >>riconnette??

no. il server rimane in attesa sulla porta che il client deve usare per connettersi.

>il client che invia un comando alla porta del server il quale
>capisce che si è riacceso e risponde creando la connessione??
se dopo il riavvio del client ti riconnetti al server viene creata una nuova connessione.

>Nel primo caso il server dovrebbe sapere la porta di ricezione
>del client, cosa improbabile. Quindi devo supporre che sia il
>client che invia la chiamata al server indicando la porta di
>ricezione. Come viene determinata la porta di ricezione???
automaticamente quando il client crea la connessione. fa tutto tcp tu non devi far nulla :D

> Se
>la porta di ricezione fosse fuori dalle standard come la definisco???

Semplificando tutto lo schema di comunicazione, TCP puoi vederlo così ...

1) il client si collega sulla porta di ricezione delle connessioni del server... (la porta di listen)

2)a quel punto il server sposta la connessione su una ulteriore porta (il numero non puoi saperlo a priori) dove avviene lo scambio dei dati. La porta di listen (cioè quella alla quale ti colleghi perché sai il numero di porta) viene usata unicamente per accettare le connessioni in ingresso.

3) il client, durante la connessione al server, apre una porta (che trovi definita come "effimera") ovvero una porta identificata da un numero scelto automaticamente dal sistema operativo. Tu puoi anche forzare questo numero ma devi andare ad interagire con i socket.


scusami se sono stato poco chiaro e per eventuali errori di scrittura ma rispondo tramite uno schermo piccolo piccolo.
>
>grazie tanto

Luigi Di Biasi
http://blogs.dotnethell.it/luigidibiasi/
http://www.dibiasi.it/

basicdany Profilo | Expert

ciao, in riferimento a questo punto chiesto da me:

Se la porta di ricezione fosse fuori dalle standard come la definisco???

la tua risposta:

b) il client, durante la connessione al server, apre una porta (che trovi definita come "effimera") ovvero una porta identificata da un numero scelto automaticamente dal sistema operativo. Tu puoi anche forzare questo numero ma devi andare ad interagire con i socket.

Come posso forzare il numero della porta su 61963,
perche' ritengo che il server non accetti la connessione perche non vede tale porta aperta,
ho visto i socket e non vedo la possibila' di forzare questa porta??

grazie tanto.

luigidibiasi Profilo | Guru

>ciao, in riferimento a questo punto chiesto da me:
>
>Se la porta di ricezione fosse fuori dalle standard come la definisco???
>
>la tua risposta:
>
>b) il client, durante la connessione al server, apre una porta
>(che trovi definita come "effimera") ovvero una porta identificata
>da un numero scelto automaticamente dal sistema operativo. Tu
>puoi anche forzare questo numero ma devi andare ad interagire
>con i socket.
>
>Come posso forzare il numero della porta su 61963,
>perche' ritengo che il server non accetti la connessione perche
>non vede tale porta aperta,
>ho visto i socket e non vedo la possibila' di forzare questa
>porta??
>

Per forzare il client ad aprire una porta con numero fissato è necessario usare l'oggetto socket. Non credo che l'oggetto TcpClient basti:

ti posto un codice di esempio:

Dim myClient As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
myClient.Bind(New System.Net.IPEndPoint(0, 61963))
myClient.Connect("IP_SERVER", "PORTA_SERVER")


ti consiglio di guardarti qui :
http://msdn.microsoft.com/it-it/library/system.net.sockets.socket.aspx

ma devi informarti un po sui socket perché non è immediato riuscirli ad usare a basso livello


>grazie tanto.

Luigi Di Biasi
http://blogs.dotnethell.it/luigidibiasi/
http://www.dibiasi.it/

basicdany Profilo | Expert

grazie del tuo prezioso aiuto, sono riuscito a collegarmi al server e ha ricevere i dati, ora mi rimane ultima cosa, rispondere io in base a delle stringhe di byte che converto, (ogni byte CHR) leggo in formato testo cosa il server mi mandi,
mi chiedo per rispondere, come devo inviare le stringhe (sono a conoscenza delle stringhe di risposta che devo inviare in testo) al server,

esempio il server mi scrive : "sei attivo" (converto ogni singolo byte in chr)
devo rispondere "OK", come devo inviarlo che tipo di conversione devo fare, ho provato a inviare una matrice di byte, ogni byte contiene il valore convertito in decimale es: "O" = a 79, e corretto??

Aspetto risposta, grazie tanto.

luigidibiasi Profilo | Guru

>devo rispondere "OK", come devo inviarlo che tipo di conversione
>devo fare, ho provato a inviare una matrice di byte, ogni byte
>contiene il valore convertito in decimale es: "O" = a 79, e corretto??

devi conoscere come il server attende i messaggi di risposta:

ad esempio OK + chr(13) = { testo ok + carrier return}

io personalmente uso una cosa del genere

' stringa da inviare la scrivi in un oggetto string
Dim sToSend As String = "OK" + vbcrlf
' utilizzi le classi .net per ricavarti l'array di byte
Dim toSend As Byte() = System.Text.Encoding.ASCII.GetBytes(sToSend)
' invii la stringa
mys.Send(toSend)


>
>Aspetto risposta, grazie tanto.

Luigi Di Biasi
http://blogs.dotnethell.it/luigidibiasi/
http://www.dibiasi.it/

basicdany Profilo | Expert

ciao, la stringa che devo inviare e la seguente in esadecimale:
34 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 4f 4b 20 30

che corispondono a 50 byte

che in decimale è "4 OK 0"

io ho provato a inviarla creando un array di 50 byte e inserendo nelle varie posizioni il carattere corispondente in decimale:

52 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 79 75 32 48

sender.sent(byte)

il byte ha 50 unita, ma e corretto il modo in cui invio visto che non funziona?

grazie aspetto risposta.



luigidibiasi Profilo | Guru

>ciao, la stringa che devo inviare e la seguente in esadecimale:
> 34 00 00 00 00 00 00 00 00 00
>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>00 00 00 00 4f 4b 20 30
>
>che corispondono a 50 byte
>
>che in decimale è "4 OK 0"
>
>io ho provato a inviarla creando un array di 50 byte e inserendo
>nelle varie posizioni il carattere corispondente in decimale:
>
> 52 0 0 0 0 0 0 0 0 0
> 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
> 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
> 0 0 0 0 79 75 32 48
>
>sender.sent(byte)
>
>il byte ha 50 unita, ma e corretto il modo in cui invio visto
>che non funziona?

visto che funziona.... direi di si

Forse può risultati utile creare una lista di costanti di tipo byte(50) all'interno del programma così le tieni sempre pronte per inviarle...

>grazie aspetto risposta.
>
>
>
>

Luigi Di Biasi
http://blogs.dotnethell.it/luigidibiasi/
http://www.dibiasi.it/

basicdany Profilo | Expert

Ciao grazie tanto per l'interesse,
forse non mi sono spiegato prima, dicevo che non funziona, funzionerebbe se il server invia altri tipi di dati e non quelli generici,

il server quando riceve dal client la stringa "OK 0" cambio stato e comincia a inviare certi tipi di dati, questo non avviene ancora!

riesco a collegarmi ricevo i dati generici che ricevono tutti i client appena collegati,

la domanda era quindi se e corretto mandare l'array di byte con i caratteri convertiti in decimali nelle rispettive posizioni dell'array di byte?

in questa maniera:

Private Sub ReceiveCallback(ByVal ar As IAsyncResult)

Dim Byte4 As String = Chr(0) & Chr(0) & Chr(0) & Chr(0)
Dim Byte8 As String = Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0)
Dim Byte16 As String = Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0)


' Retrieve the state object and the client socket
' from the asynchronous state object.
Dim state As StateObject = CType(ar.AsyncState, StateObject)
Dim client As Socket = state.workSocket

If Not client.Connected Then
receiveDone.Set()
Dim dlg As New DisconnectResponseDataDelegate(AddressOf DisconnectResponse)
Me.Invoke(dlg)
Exit Sub
End If

' Read data from the remote device.
Dim bytesRead As Integer = client.EndReceive(ar)

If bytesRead > 0 Then
'Store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead))

'Put it in a response.
If state.sb.Length > 1 Then
response = state.sb.ToString()
End If

Else
'Server Has disconnected
client.Close()
receiveDone.Set()
Dim dlg As New DisconnectResponseDataDelegate(AddressOf DisconnectResponse)
Me.Invoke(dlg)
Exit Sub
End If

If response.IndexOf("ACTIVE") > -1 Then
'Send message to Server thread
Dim dlg As New ShowReceiveDataDelegate(AddressOf ShowReceiveData)
Me.Invoke(dlg, response)

'Clear the buffer and response
response = Nothing
Array.Clear(state.buffer, 0, bytesRead)
state.sb.Remove(0, bytesRead)
'Get the next of the message
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReceiveCallback), state)

' Signal that all bytes have been received.
receiveDone.Set()

'RISPOSTA AL COMANDO ACTIVE DRV con "OK 0"
Send(client, "4" & Chr(0) & Byte8 & Byte16 & Byte16 & Byte4 & "OK" & " " & "0")

end if
end sub

HO fatto prove in sincrono e ora come vedi sopra con i socket in asincrono, ma non funziona, fra asincrono e sincrono ci sono differenze?

ciao aspetto risposta grazie

luigidibiasi Profilo | Guru

>Ciao grazie tanto per l'interesse,
>forse non mi sono spiegato prima, dicevo che non funziona, funzionerebbe
>se il server invia altri tipi di dati e non quelli generici,
>
>il server quando riceve dal client la stringa "OK 0" cambio stato
>e comincia a inviare certi tipi di dati, questo non avviene ancora!
>
>riesco a collegarmi ricevo i dati generici che ricevono tutti
>i client appena collegati,

ok quindi il problema è come mandare OK 0

>
>la domanda era quindi se e corretto mandare l'array di byte con
>i caratteri convertiti in decimali nelle rispettive posizioni
>dell'array di byte?
>
>in questa maniera:
>

> Private Sub ReceiveCallback(ByVal ar As IAsyncResult)
>
> Dim Byte4 As String = Chr(0) & Chr(0) & Chr(0) & Chr(0)
>Dim Byte8 As String = Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0)
>& Chr(0) & Chr(0) & Chr(0)
>Dim Byte16 As String = Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0)
>& Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0)
>& Chr(0) & Chr(0) & Chr(0) & Chr(0)
>

potrebbe essere corretto... prova ad inserire un chr(13) al posto dell'ultimo chr(0)
forse il server si attende un [invio] per accettare la stringa...

devi fare prove così perché non sappiamo di preciso come il server si attende i dati...


Luigi Di Biasi
http://blogs.dotnethell.it/luigidibiasi/
http://www.dibiasi.it/
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-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5