Nie wiem co chcesz osiągnąć w końcu, ale praca z UDP nie jest tak łatwo ... głównym powodem jest w Opisie Przedmiotu DatagramPacket:
pakiety strumieniowe są używane do implementuj usługę dostarczania pakietów bezpołączeniowych: . Każda wiadomość jest kierowana z jednej maszyny do innej, opartej wyłącznie na na informacji zawartej w pakiecie . Wiele pakietów wysłanych z z jednego komputera do drugiego może być inaczej kierowanych i może przybyć do dowolnej kolejki . Dostarczenie paczki nie jest gwarantowane na .
Dobry poradnik podczas pracy z UDP jest http://download.oracle.com/javase/tutorial/networking/datagrams/clientServer.html
O swojej blokowania:
otrzymuje pakiet datagramowy z tego gniazda . Gdy ta metoda zostanie zwrócona, bufor DatagramPacket zostanie wypełniony otrzymanymi danymi. Pakiet datagramowy zawiera również adres IP nadawcy, i numer portu na urządzeniu nadawcy .
Ta metoda blokuje do momentu otrzymania datagramu w postaci . Pole długości obiektu pakietów datagramów o nazwie zawiera długość odebranej wiadomości. Jeśli komunikat jest dłuższy niż długość pakietu , wiadomość jest obcięta.
ja naprawdę nie przetestować go, ale jestem całkiem pewny, że - na podstawie opisu - że funkcja datagramsocket.reseive zablokuje aż pakiet zostanie wypełniony (w przypadku aż 100000 bajtów są odbierane).
Proponuję rozpocząć od datagrampacket o stałej znanej długości, w której transmitowany jest rozmiar rzeczywistej ładowności.Coś jak:
public static void main(String[] args) {
ClientModel c1 = new ClientModel();
c1.data = 123;
c1.name = "test";
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(c1);
oos.flush();
// get the byte array of the object
byte[] Buf= baos.toByteArray();
int number = Buf.length;;
byte[] data = new byte[4];
// int -> byte[]
for (int i = 0; i < 4; ++i) {
int shift = i << 3; // i * 8
data[3-i] = (byte)((number & (0xff << shift)) >>> shift);
}
DatagramSocket socket = new DatagramSocket(1233);
InetAddress client = InetAddress.getByName("localhost");
DatagramPacket packet = new DatagramPacket(data, 4, client, 1234);
socket.send(packet);
// now send the payload
packet = new DatagramPacket(Buf, Buf.length, client, 1234);
socket.send(packet);
System.out.println("DONE SENDING");
} catch(Exception e) {
e.printStackTrace();
}
}
Z drugiej strony teraz znać swoje rozmiary:
public static void main(String[] args) {
try {
DatagramSocket socket = new DatagramSocket(1234);
byte[] data = new byte[4];
DatagramPacket packet = new DatagramPacket(data, data.length);
socket.receive(packet);
int len = 0;
// byte[] -> int
for (int i = 0; i < 4; ++i) {
len |= (data[3-i] & 0xff) << (i << 3);
}
// now we know the length of the payload
byte[] buffer = new byte[len];
packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
ByteArrayInputStream baos = new ByteArrayInputStream(buffer);
ObjectInputStream oos = new ObjectInputStream(baos);
ClientModel c1 = (ClientModel)oos.readObject();
c1.print();
} catch(Exception e) {
e.printStackTrace();
}
}
clas CientModel sI używane:
public class ClientModel implements Serializable{
private static final long serialVersionUID = -4507489610617393544L;
String name = "";
int data = 1;
void print() {
System.out.println(data +": " + name);
}
}
testowałem ten kod i to działa dobrze. Nadzieja, która pomaga (mam bajt-To-int i okolice od http://www.tutorials.de/java/228129-konvertierung-von-integer-byte-array.html)
Edycja: jak stwierdzono w komentarzach, często bardzo złym pomysłem jest używanie UDP, głównie, ponieważ nie wiesz, czy twoje pakiety są odbierane we właściwej kolejności, a nawet w ogóle. UDP NIE gwarantuje tego. Nie robiłem zbyt wiele programowania udp, ale jedyną częścią, na której możesz polegać (jeśli dobrze zrozumiałem) jest to, że jeśli dostaniesz pakiet i pasuje on do datagramu (65 527 bajtów - patrz https://en.wikipedia.org/wiki/User_Datagram_Protocol) to będzie zawierał całość rzecz. Więc jeśli nie zależy ci na kolejności, w jakiej wiadomość przychodzi, a twój obiekt pasuje do datagramu, powinieneś być w porządku.
Edycja2: Jeśli chodzi o kod: nie używaj go jak jest. jest to tylko przykład, ind UDP powinieneś mieć tylko jeden typ pakietu, a ten o znanym rozmiarze. w ten sposób nie musisz wysyłać "rozmiaru". Jeśli użyjesz kodu pokazanego powyżej, a jeden pakiet zostanie upuszczony, następny pakiet będzie miał nieprawidłowy rozmiar (tzn. Pierwszy pakiet zostanie upuszczony, nagle sprawdzasz pierwsze bajty ładunku, aby uzyskać rozmiar).
może trzeba przepłukać bufor ... – ultrajohn