Permalänk
Medlem

Java nätverksprogrammering

Hej!

Jag håller på att skriva ett "Skissa och gissa"-program som hobbyprojekt. Just nu har jag kommit så långt att man kan rita och chatta. Alltså har jag lyckats komma en bit med nätverksprogrammeringen.
Problemet jag har är när man ska skicka linjerna som är ritade över nätverk. Hur ska jag veta om det är ett chattmeddelande eller en linje som kommer?
Som ni ser här under använder jag mig av MulticastSocket i min Chat-klass för att många användare ska kunna ansluta sig.

import java.awt.event.*; import javax.swing.*; import java.net.*; import java.io.*; public class Chat implements ActionListener, KeyListener, Runnable { private JTextArea show; private JTextField write; private Player player; private Thread thread = new Thread(this); private int port; private MulticastSocket so; private InetAddress ina; /** * Creates a new Chat with the specific {@link JTextArea} and {@link JTextField}. * @param show A {@link JTextArea} that is used in class {@link ChatArea} to show messages * @param write A {@link JTextField} that is used in class {@link ChatArea} to write messages * @see ChatArea */ public Chat(JTextArea show, JTextField write, Player player, MulticastSocket so, InetAddress ina, int port) { this.show = show; this.write = write; this.player = player; this.so = so; this.ina = ina; this.port = port; try { so = new MulticastSocket(port); ina = InetAddress.getByName("234.235.236.238"); so.joinGroup(ina); thread.start(); send("Connected"); } catch(IOException e) { System.out.println(e); } } public void run() { byte[] data = new byte[1024]; while(true) { try { DatagramPacket packet = new DatagramPacket(data, data.length); so.receive(packet); String message = new String(data, 0, packet.getLength()); show.append(message); } catch (IOException e){ break; } } } /** * Changes the text in {@link JTextArea} and remove text in {@link JTextField} */ public void send(String s) { byte[] data = (player.getName() + ": " + s + "\n").getBytes(); DatagramPacket packet = new DatagramPacket(data, data.length, ina, port); try { so.send(packet); } catch(IOException e) { System.out.println(e); } } }

Permalänk
Medlem

Du kan göra så att du skickar "Object" med beskrivning

Exempel:

class ChatInput implements serializable { private boolean text; public ChatInput(Color c, int x, int y){ this..... text=false; } public ChatInput(String name, String msg){ this..... text=true; } public boolean isText(){ return text; } pub.... }

Eller så kan du göra att en viss ström bitar kommer i en specifik följd i början.
Exempel:
0x01 0x01 0x01 0x02 0x01 0x02 = text
0x01 0x01 0x01 0x02 0x01 0x03 = linje

0x01 0x01 0x01 0x02 0x01 0x02 0x68 0x65 0x6a 0x20 0x6b 0x61 0x6c 0x6c 0x65 = hej kalle

Visa signatur

Stationär: Ubuntu GB DQ6 P35 | Q6600 | 4GB ram Corsair 2*2gb 800mhz (3.5gb) |1tb SATA + 500gb SATA + 250gb SATA | Sparkle 9800gt Passiv
Laptop: Lenovo 3000 v200 | Ubuntu |

Permalänk
Medlem

Re: Java nätverksprogrammering

Citat:

Ursprungligen inskrivet av Jepsson
Hej!

Jag håller på att skriva ett "Skissa och gissa"-program som hobbyprojekt. Just nu har jag kommit så långt att man kan rita och chatta. Alltså har jag lyckats komma en bit med nätverksprogrammeringen.
Problemet jag har är när man ska skicka linjerna som är ritade över nätverk. Hur ska jag veta om det är ett chattmeddelande eller en linje som kommer?
Som ni ser här under använder jag mig av MulticastSocket i min Chat-klass för att många användare ska kunna ansluta sig.

Om du föredrar ett text-protokoll så kan du ju alltid inleda varje rad med ett ord som identifierar vad raden betyder, t.ex.

LINE ... \n
MSG ... \n

Om du istället föredrar ett binärprotokoll så kan du ju paketera in allt i paket som inleds med storlek och typ, t.ex.

struct { // c-style.
uint32_t size;
uint32_t type;
....
// specifikt för denna typ.
};

Du ska inte använda "serializable".

Visa signatur

Intel Core i7-3770K | NVIDIA Geforce GTX 980 | 16 GB DDR3 | DELL P2415Q | DELL U2711 | DELL U2410

Permalänk
Medlem

Re: Re: Java nätverksprogrammering

Citat:

Ursprungligen inskrivet av MagnusL
Om du föredrar ett text-protokoll så kan du ju alltid inleda varje rad med ett ord som identifierar vad raden betyder, t.ex.

LINE ... \n
MSG ... \n

Om du istället föredrar ett binärprotokoll så kan du ju paketera in allt i paket som inleds med storlek och typ, t.ex.

struct { // c-style.
uint32_t size;
uint32_t type;
....
// specifikt för denna typ.
};

Du ska inte använda "serializable".

Varför ska man inte använda serializable? Han använder sig av Java och inte C/C++. Visst om det ska fungera för alla typer av språk så ska han identifiera med bytes (ord (som irc) eller en viss följd)

struct finns inte i java.

Visa signatur

Stationär: Ubuntu GB DQ6 P35 | Q6600 | 4GB ram Corsair 2*2gb 800mhz (3.5gb) |1tb SATA + 500gb SATA + 250gb SATA | Sparkle 9800gt Passiv
Laptop: Lenovo 3000 v200 | Ubuntu |

Permalänk
Medlem

Tack för svaren. Jag har gjort så att jag använder ett textprotokoll, problemet med detta är vad jag förstår att man endast kan skicka strängar, eller har jag uppfattat fel? Iofs gör det mig inte så mycket eftersom mina linjer ganska lätt kan anges i strängform.

Permalänk
Medlem

Det finns väl nån smidig XML-klass du kan använda?

Visa signatur

www.filipsprogram.tk - lite freeware
"Delight, herregud. Talang är bara förnamnet."

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Jepsson
Tack för svaren. Jag har gjort så att jag använder ett textprotokoll, problemet med detta är vad jag förstår att man endast kan skicka strängar, eller har jag uppfattat fel? Iofs gör det mig inte så mycket eftersom mina linjer ganska lätt kan anges i strängform.

Du menar att du vill kunna skicka siffror som siffror? Det är tyvärr omöjligt i den form du tänker på. Man kan bara skicka data, och om det är ett tal som skickas kan du köra t.ex. int.Parse och få ut data som ett tal. Men när data skickas skiljs inte strängar, tal, decimaltal eller andra objekt åt, utan allt är bara data.

Därmed är det upp till mottagaren att tolka det data den får in och ge tillbaka rätt datatyper. Serializable som någon nämner ovan är enklast att använda, i C# är det rena drömmen och jag kan tänka mig att det fungerar bra i Java också.

Permalänk
Medlem

Hej igen!

Efter en del trixande och pillande har jag nu använt Serializable och ganska precis den taktiken som Sockan beskriver först, det fungerar bra och var ganska lätt att fixa efter att ha kollat runt lite på nätet.

Men nu har jag ett till problem. När man startar programmet får man upp en dialogruta där man skriver in sitt namn, sen skickar jag en request till alla som ingår i multicast-gruppen för att få deras namn och ge mitt namn. Problemet blir då när jag ska bestämma vem som får rita först.
Jag provade med:

send(new Send(player.getName(), 2)); if(playersarea.getNumberOfPlayers() == 1) { drawingarea.setEnabled(true); colorsarea.setEnabled(true); }

Men detta fungerar inte eftersom man inte skickar och tar emot meddelande tillräckligt snabbt. Här kommer det aldrig bli 1 eftersom programmet är såpass snabbt.
Så hur ska jag nu lösa detta problem?