30. marts 2010 - 21:48Der er
58 kommentarer og 1 løsning
Fildeling -> VB.NET Client og Java Server
Hej eksperter.
Sagen er den, at jeg har lavet en chat server i Java, men selve klienterne til chatten er skrevet i VB.NET. Jeg vil nu prøve at implementere fildeling, så brugerne kan udveksle screenshots/billeder. Men det virker næsten umuligt at finde eksempler på VB.net client -> Java server -> VB.net client fildeling.
Søger råd til om det overhovedet er muligt, hvad jeg skal gøre osv - og meget gerne eksempler.
Jeg vil tro svaret er tekstprotokol, da jeg bruger for eksempel bruger printstream.println(string); printstream.flush(); i min Java server. Har aldrig haft den helt store forstand på bytes.
client1->server: FILE foobar.jpg server->client2: FILE foobar.jpg client1 aabner ny socket forbindelse til server client2 aabner ny socket forbindelse til server client 1 laeser fra fil og skriver til den nye socket server laeser fra client1 socket og skriver til client2 socket client2 laeser fra socket og skriver til fil
Men eftersom jeg bruger tekst protokol, skal jeg så konvertere bytesne fra billedet til et string og sende det fra client1, hvorefter client2 laver det om til bytes igen og smider det ind i en fil? Eller er jeg nødt til at bruge en binær protokol?
public class Server { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(9999); Socket s = ss.accept(); InputStream is = s.getInputStream(); OutputStream os = new FileOutputStream("C:\\z2.zip"); byte[] b = new byte[10000]; int n; while((n = is.read(b)) >= 0) { os.write(b, 0, n); } os.close(); is.close(); } }
Imports System Imports System.IO Imports System.Net Imports System.Net.Sockets
Public Class Client Public Shared Sub Main(args As String()) Dim cli As New TcpClient("localhost", 1234) Dim nstm As Stream = cli.GetStream() Dim fstm As Stream = New FileStream("C:\z.1", FileMode.Open, FileAccess.Read) Dim b As Byte() = New Byte(9999) {} Dim n As Integer While (n = fstm.Read(b, 0, b.Length)) > 0 nstm.Write(b, 0, n) End While nstm.Close() fstm.Close() cli.Close() End Sub End Class
Tak for svarene. Så du mener altså at jeg skal åbne en ny forbindelse for hver fildeling der kører binært, men samtidig holde min tekstprotokol åben?
Har desuden læst noget om peer to peer teknologi. Vil det være muligt at åbne en kortvarig 'server' på min modtagende klient? Altså ligesom MSN gør, når der sendes billeder frem og tilbage.
Det vil ikke være noget problem. Hvor kan jeg læse/se eksempler på hvordan det ville fungere i VB.NET? Og når man deler filer over MSN og scanner sine packets, kan man se at modparten og en selv bruger en tilfældig port, hvad er det for noget?
Hmm, vil det så sige at serversiden skal åbne den port i deres NAT? Det jeg tænkte på var, at den automatisk fandt en åben port. Da jeg kørte en CSS server, kunne jeg ikke få åbnet den port jeg ville have åbnet, 27015, men i stedet endte porten med at være 64117, et højt og tilfældigt tal.. Er det kun muligt med UDP?
1. Åbner en ny forbindelse på en ny port. 2. Ber begge parter om at connecte. 3. Får senderen til at sende det der skal sendes og omdirigerer alt data til modtageren.
Som en forhåbentlig afslutning på det hele: Jeg har forsøgt at lave det uden om Java serveren, altså simpelthen bare fra VB.NET -> VB.NET.
Det eneste problem jeg har er at den modtagne fil fylder 8 KB mens den sendte fil fylder 27 KB. Jeg går ud fra at det skyldes, at jeg mangler et loop ved min modtagelse.
Dim c As TcpClient = server.AcceptTcpClient Dim s As NetworkStream = c.GetStream
Dim inStream(c.ReceiveBufferSize) As Byte s.Read(inStream, 0, c.ReceiveBufferSize) FilePut(1, inStream)
FileClose(1)
Dog giver et loop som "While NetWorkStream.CanRead" en fil der bliver ved med at vokse og dermed aldrig slutter. Hvilket loop skal jeg placere der for at få netop den fil jeg forsøger at modtage?
Min modtager: Dim c As TcpClient = server.AcceptTcpClient Dim s As NetworkStream = c.GetStream FileOpen(1, filePath, OpenMode.Binary) Dim b As Byte() = New Byte(9999) {} Dim n As Integer n = s.Read(b, 0, b.Length) While n > 0 n = s.Read(b, 0, b.Length) FilePut(1, b) End While
Min sender: Dim cli As New TcpClient("localhost", 1300) Dim nstm As Stream = cli.GetStream() Dim fstm As Stream = New FileStream(filePath, FileMode.Open, FileAccess.Read) Dim b As Byte() = New Byte(9999) {} Dim n As Integer While (n = fstm.Read(b, 0, b.Length)) > 0 nstm.Write(b, 0, n) End While
Hvor ligger fejlen? Som sagt har jeg ikke den store forstand på binært. Jeg beklager alle disse spørgsmål. Hvis du ønsker det kan jeg tildele flere point for al din hjælp.
Ja, både serversiden og klienten kommer til det stykke kode. Der opstår ingen exceptions under forløbet. Både klienten og serveren starter en ny tråd til forbindelserne, så det ikke påvirker mit UI.
Fandt dette stykke kode: Public Sub TransferData(ByVal FromStream As IO.Stream, ByVal ToStream As IO.Stream, ByVal BufferSize As Integer) Dim buffer(BufferSize - 1) As Byte Do While True Dim bytesRead As Integer = FromStream.Read(buffer, 0, buffer.Length) If bytesRead = 0 Then Exit Do ToStream.Write(buffer, 0, bytesRead) ToStream.Flush() Loop End Sub
Får dog fejl når jeg bruger det, eftersom serveren åbenbart ikke vil modtage noget, og den hopper direkte til server.close().
Problem løst, brugte det samme stykke kode ved min modtager: Dim c As TcpClient = server.AcceptTcpClient Dim s As NetworkStream = c.GetStream FileOpen(1, filePath, OpenMode.Binary) Dim buffer(1024 - 1) As Byte Do While True Dim bytesRead As Integer = s.Read(buffer, 0, buffer.Length) If bytesRead = 0 Then Exit Do FilePut(1, buffer) Loop FileClose(1)
Forstår dog stadig ikke hvorfor dit eksempel ikke virkede, det er nogenlunde det samme.
Okay. Jeg tester i øjeblikkeligt binær kommunikation fra vb.net -> java.
Jeg sender et string således: Public Sub sendString(ByVal str As String) s.Write(Encoding.ASCII.GetBytes(str), 0, Encoding.ASCII.GetBytes(str).Length) s.Flush() End Sub
Har læst den guide du linkede til, min java server ser således ud: dis = new DataInputStream(socket.getInputStream()); dos = new DataOutputStream(socket.getOutputStream());
byte firstPacket = dis.readByte();
For at afkode bytes til strings ville jeg i vb.net bruge Encoding.ASCII.getString(byte), hvad skal jeg i java? Eller skal jeg tage hensyn til det med big og little endian? -tetrix.
Min ide var at sende al meta information: modtager, filnavn, filstørrelse, vindretningen etc. på den permanente tekst socket forbindelse og kun sende filens bytes over den binære engangs socket.
Har fundet en løsning på overstående problem. byte[] buffer = new byte[1024]; boolean r = true; while(r){ int n = dis.read(buffer, 0, buffer.length); if(n==0)r=false; String str = new String(buffer, "UTF-8"); if(str.contains("alias,")) logLine(str); }
Efter det data jeg skal modtage kommer der dog en masse whitespace, hvad skal jeg gøre for at slippe af med det?
Har fået sat forbindelserne sammen, og kører nu rent binært. Det har lykkedes mig at sende dele af et billede i visse tilfælde, men jeg mangler en færdig løsning. Har brugt dit eksempel som Java server, og i mine vb.net klienter de dele jeg brugte til vb.net -> vb.net, som beskrevet i #29.
dis (datainputstream) = sender af filen dos (dataoutputstream) = modtager af filen
byte[] buffer = new byte[1024]; int n; while((n = dis.read(buffer, 0, buffer.length)) > 0){ dos.write(buffer, 0, n); dos.flush(); }
Problemet er at Java serveren ikke kan se hvornår jeg stopper med at modtage, men det kan senderen til gengæld.
Derfor får modtageren aldrig brugt FileClose(*), før jeg altså lukker programmet.. Mener at jeg har hørt noget om Java og bytes der ikke ville returne e.l. et sted.. Skal jeg igen blande tekst og binær for at få senderen til at fortælle hvornår den er sendt? Tak.
Får begge parter til at connecte til min "binary server". Når begge parter er forbundet, bliver senderen bedt om at sende.
Siden senderen kan se hvornår filen er sendt, lukker den forbindelsen efter det hele er sendt. På den måde kan serveren også følge med. Ved ikke om det er en helt god metode, men det virker.
Og hvordan kan jeg "markere" længden? Går også ud fra, at det er her delen om big og little endian kommer ind.
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.