Send UDP message every X second in Java - java

I'm trying to send a message every X second with UDP protocol, but with this code, only one message is sending, and no error appear. Can you help me ?
This is my main where there is a loop and a sleep for 1 second :
Thread t = new Thread(){
#Override
public void run() {
while(true) {
try {
UDPSender sender = new UDPSender(1000, "localhost");
sender.send("message");
sender.close();
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
t.start();
And here is my class UDPSender which manage UDP and permit to send the message (this works but I put it FYI) :
public class UDPSender {
private DatagramSocket socket;
private InetAddress address;
private int port;
private byte[] buf;
public UDPSender(int port, String address) {
this.port = port;
try {
this.socket = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
try {
this.address = InetAddress.getByName(address);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public String send(String msg) {
System.out.println(LocalDateTime.now() + " - sent: " + msg);
this.buf = msg.getBytes();
DatagramPacket packet
= new DatagramPacket(this.buf, this.buf.length, this.address, this.port);
try {
this.socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
packet = new DatagramPacket(this.buf, this.buf.length);
try {
this.socket.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
return new String(packet.getData(), 0, packet.getLength());
}
public void close() {
this.socket.close();
}

Related

Java how to read with ObjectInputStream

It's my first time working with sockets, in order to get a better understanding of what's going on I decided to build a client server chat application which can support several users.
At first, I used DataInputStream / DataOutputStream to communicate and everything works well. But I would like to switch to an ObjectStream and that's where the problem occurs. Once I replace all the DataInputStream / DataOutputStream by ObjectInputStream / ObjectOutputStream, I'm no longer able to print the retrieved data.
This is the code that I used before, which works (DataStream) :
SERVER:
try {
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF("HI FROM SERVER");
while (!socket.isClosed()) {
try {
if (in.available() > 0) {
String input = in.readUTF();
for (ClientThread thatClient : server.getClients()){
DataOutputStream outputParticularClient = new DataOutputStream(thatClient.getSocket().getOutputStream());
outputParticularClient.writeUTF(input + " GOT FROM SERVER");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
CLIENT:
try {
socket = new Socket("localhost", portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
new Thread(()->{
while(!socket.isClosed()){
try {
if (in.available() > 0){
String input = in.readUTF();
System.out.println(getUserName() + " > " + input);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
And this is how I tried to perform the same idea with ObjectStream :
SERVER:
try {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
while (!socket.isClosed()) {
try {
if (in.available() > 0) {
Message input;
try {
input = (Message)in.readObject();
if (input.equals(null)){
System.err.println("SERVER RETRIEVED NULL OBJECT");
}
for (ClientThread thatClient : server.getClients()){
ObjectOutputStream outputParticularClient = new ObjectOutputStream(thatClient.getSocket().getOutputStream());
outputParticularClient.writeObject(input);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
CLIENT:
try {
socket = new Socket(getHost(), portNumber);
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
new Thread(()->{
while(!socket.isClosed()){
try {
if (in.available() > 0){
Message input = null;
try {
input = (Message)in.readObject();
if (input.equals(null)){
System.err.println("CLIENT RETRIEVED NULL OBJECT");
}
System.out.println("CLIENT " + input.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
I feel like it has something to do with this if statement if (in.available() > 0) but I cannot say precisely what's going on.
available() doesn't do what you may think it does and it is almost never useful in production code (and that's particularly true for ObjectInputStream). The reason you don't receive any data is in fact that in.available() always returns 0 as you already suspected.
As noted in the comments, the StreamCorruptedException is caused by writing to an existing ObjectInputStream that has already been written to using another instance of ObjectOutputStream. Cf. the answer StreamCorruptedException: invalid type code: AC for further explanation.
Here is some quick & dirty example code that has a server echoing the messages from two clients. It's not clean but it may give you an idea how to approach your problem:
public class SO56493162 {
private static final class Message implements Serializable {
private static final long serialVersionUID = 1L;
private static int cnt = 0;
private final int id;
public Message(int id) {
++cnt;
this.id = id;
}
public String toString() {
return "Msg from " + id + " : " + cnt;
}
}
private static final class Client implements Runnable {
private InetSocketAddress addr = null;
private int id = -1;
Client(InetSocketAddress addr, int id) {
this.addr = addr;
this.id = id;
}
public void run() {
int timeout = 3000;
Socket s = null;
try {
s = new Socket();
s.connect(addr, timeout);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
System.out.println("Client " + id + " connected");
while (true) {
Thread.sleep(new Random().nextInt(2000));
Message hello = new Message(id);
oos.writeObject(hello);
oos.flush();
Message reply = (Message) ois.readObject();
System.out.println("Reply: " + reply.toString());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
s.close();
} catch (Exception ignore) {
}
}
}
}
private static final class Server implements Runnable {
private ServerSocket sock = null;
Server(ServerSocket sock) throws IOException {
this.sock = sock;
}
public void run() {
System.out.println("starting server");
try {
while (true) {
final Socket client = sock.accept();
System.out.println("connection accepted");
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
while (!client.isClosed()) {
try {
Message input = (Message) ois.readObject();
oos.writeObject(input);
oos.flush();
} catch (EOFException eof) {
System.err.println("EOF!");
client.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) throws IOException, InterruptedException {
final int port = 9876;
Thread ts = new Thread(new Runnable() {
#Override
public void run() {
try {
new Server(new ServerSocket(port)).run();
} catch (Exception e) {
e.printStackTrace();
}
}
});
ts.setDaemon(true);
ts.start();
InetSocketAddress addr = new InetSocketAddress("localhost", port);
for (int i = 0; i < 2; ++i) {
Client cl = new Client(addr, i);
Thread tc = new Thread(cl);
tc.setDaemon(true);
tc.start();
}
Thread.sleep(10000);
System.err.println("done");
}
}

Android client/server application - proper way to receive messages continously

I'm trying to make a client/server application using an Android phone as a client using AsyncTask to send messages from UI.
I've written some very basic implementation just to test the connection and the way that messages are received / sent and I found a very big problem.
The client part seems to work fine..from my perspective. But the server part is the problem. I can't make the server reading and displaying messages countinously from the client.
I tried something like while(line = (in.readLine()) != null) {} but it doesn't seems to work.
After I sent my first word from the client, the server reads null and it stops.
Can someone show me a proper way to keep the server running while the client is not sending nothing?
I'd like to avoid using while(true) if it's not 100% necessary.
Here is the implementation until now:
Server:
public class SocketServerThread extends Thread {
private static final Logger log = Logger.getLogger(SocketServerThread.class);
private static final int SERVER_PORT_NUMBER = 5000;
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(SERVER_PORT_NUMBER);
serverSocket.setReuseAddress(true);
log.info("Waiting for connection...");
Socket clientSocket = serverSocket.accept();
log.info("Connected! Receiving message...");
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
try {
while (true) {
String line = in.readLine();
if (line != null) {
log.info(line);
}
}
} catch (Exception e) {
log.error("Unexpected exception while sending / receiving messages.");
e.printStackTrace();
} finally {
in.close();
clientSocket.close();
serverSocket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Client:
public class MyAsyncTask extends AsyncTask<String, Integer, String> {
private static final String TAG = "MyAsyncTask";
private static final String SERVER_IP_ADDRESS = "10.0.2.2";
private static final int SERVER_PORT_NUMBER = 5000;
private PrintWriter out;
#Override
protected String doInBackground(String... params) {
String message = "";
try {
InetAddress address = InetAddress.getByName(SERVER_IP_ADDRESS);
Log.d(TAG, "Connecting...");
Socket socket = new Socket(address, SERVER_PORT_NUMBER);
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
Log.d(TAG, "I/O created");
message = params[0];
if (!message.equals("stop")) {
sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
out.flush();
out.close();
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
private void sendMessage(String message) {
if (out != null && !out.checkError()) {
out.println(message);
out.flush();
Log.d(TAG, "Sent message: " + message);
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.d(TAG, "onPostExecute(), s: " + s);
}
Thank you.
The problem is that your BufferedReader only read the first input stream. In order to receive the text after that, you have to re-read the input stream. I do it by recreating the socket when I am done reading, so that I can read next coming data. I am using the following code in my app. You can use this
private ServerSocket serverSocket;
public static final int SERVERPORT = 5000;
Thread serverThread = null;
public void startSocketServer(){
this.serverThread = new Thread(new ServerThread());
this.serverThread.start();
}
public void stopSocket(){
if(serverSocket != null){
try{
serverSocket.close();
}
catch (IOException e){
e.printStackTrace();
}
}
}
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
Log.wtf(TAG,"Socket: New Socket");
serverSocket = new ServerSocket(SERVERPORT);
if(serverSocket == null){
runOnUiThread(new Runnable() {
#Override
public void run() {
startSocketServer();
}
});
return;
}
while (!Thread.currentThread().isInterrupted() && !serverSocket.isClosed()) {
try {
socket = serverSocket.accept();
Log.wtf(TAG,"Socket: Accepting");
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (IOException e) {
Log.wtf(TAG,"Socket: Error");
e.printStackTrace();
}
if(Thread.currentThread().isInterrupted()){
Log.wtf(TAG, "Thread Interrupted");
}
if(serverSocket.isClosed()){
Log.wtf(TAG, "serverSocket closed");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class CommunicationThread implements Runnable {
private Socket clientSocket;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
log.info("Connected! Receiving message...");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
try {
while (true) {
String line = in.readLine();
if (line != null) {
log.info(line);
}
else
break;//This will exit the loop and refresh the socket for next data
}
} catch (Exception e) {
log.error("Unexpected exception while sending / receiving messages.");
e.printStackTrace();
}
finally {
in.close();
clientSocket.close();
}
refreshSocket();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void refreshSocket(){
runOnUiThread(new Runnable() {
#Override
public void run() {
stopSocket();
startSocketServer();
}
});
}
Just call startSocketServer() to start the server socket in your code.

Byte[] sent across SocketChannel but not received

I've been having some trouble with a project that requires a bit of networking, where data is sent over a SocketChannel but is never received. I was able to replicate the issue with a simple localhost chatroom program (sorry if it's a bit messy):
public class Main {
private Sender sender;
private Receiver receiver;
public static void main(String[] args) {
Main foo = new Main();
//The ports are switched in the other running version of this
foo.receiver = new Receiver("192.168.1.108", 12348);
foo.sender = new Sender("192.168.1.108", 12347);
foo.takeUserInput();
}
private void takeUserInput() {
while(true) {
System.out.println("Enter something");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = null;
try {
input = br.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sender.send(input);
}
}
}
public class Receiver implements Closeable {
private InetSocketAddress bindAddress;
private ServerSocketChannel server;
private ListenThread listenThread;
public Receiver(String address, int port) {
bindAddress = new InetSocketAddress(address, port);
bind();
listen();
}
public void bind() {
try {
server = ServerSocketChannel.open();
server.configureBlocking(true);
server.bind(bindAddress);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Bound to port " + bindAddress.getPort());
}
public void listen() {
listenThread = new ListenThread();
listenThread.start();
}
private class ListenThread extends Thread {
private SocketChannel client;
public void run() {
try {
client = server.accept();
System.out.println("Received connection from " + client.getLocalAddress());
} catch (IOException e) {
e.printStackTrace();
}
while((server.isOpen()) && (client.isOpen())) {
byte[] bytes = new byte[4096];
ByteBuffer buffer = ByteBuffer.wrap(bytes);
try {
System.out.println("Reading");
client.read(buffer);
System.out.println(new String(buffer.array()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
#Override
public void close() throws IOException {
server.close();
listenThread.client.close();
}
}
public class Sender implements Closeable {
private InetSocketAddress connectAddress;
private SocketChannel clientChannel;
public Sender(String address, int port) {
connectAddress = new InetSocketAddress(address, port);
connect();
}
public void connect() {
while((clientChannel == null) || (!(clientChannel.isConnected()))) {
try {
clientChannel = SocketChannel.open(connectAddress);
} catch (IOException e) {
e.printStackTrace();
}
}
try {
System.out.println("Connected to " + clientChannel.getLocalAddress());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void send(String message) {
byte[] bytes = message.getBytes();
ByteBuffer buffer = ByteBuffer.wrap(bytes);
try {
clientChannel.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Sent message");
}
#Override
public void close() throws IOException {
clientChannel.close();
}
}
Here's the logs from one version:
Bound to port 12348
Reading
Connected to /192.168.1.108:64699
Enter something
thing
Sent message
Enter something
And the other:
Bound to port 12347
Reading
Connected to /192.168.1.108:64698
Enter something
So, I know that both programs successfully establish connections to the other, and start reading, but when I send something over a SocketChannel from one end, the other just remains stuck on the read()call in ListenThread.
How can I make the client successfully read what is sent?
I can see two issues.
As mentioned by #Ethan F, the ports are different. You should use the same port number.
Your listen() method in the Receiver class never get called. You need to call this method to accept connection.
foo.receiver = new Receiver("192.168.1.108", 12348);
foo.receiver.listen();

zeromq SYNCHRONOUS REQUEST/RESPONSE fifo

I have a server for zeromq reply like this:
public static void runDocRequirementServer() throws Exception {
ZMQ.Socket.bind("tcp://localhost:5555");
//boolean serverBusy = false;
while (!Thread.currentThread().isInterrupted()) {
// Wait for next request from the client
//byte[] request = ZeroMqServerFactory.ZMQ_SERVER.recv(0);
//System.out.println("Received Hello");
//boolean hasRecieveMore = ZeroMqServerFactory.ZMQ_SERVER.hasReceiveMore();
byte[] recv = ZeroMqServerFactory.ZMQ_SERVER.recv();
//serverBusy = true;
System.out.println("RECV MESSAGE!");
Object receivedObject = null;
//DocRequirement docRequirementRecv = null;
try {
receivedObject = ByteObjectManipulator.deserialize(recv);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if(!(receivedObject instanceof DocRequirement)) {
continue;
}
DocRequirement docRequirement = (DocRequirement) receivedObject;
System.out.println("Received: " + docRequirement.getId());
//docRequirementRecv.setId(99);
DocProduced docProduced = new DocProduced();
docProduced.setId(docRequirement.getId() + 1);
byte[] objectSerialized = ByteObjectManipulator.serialize(docProduced);
// Do some 'work'
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Send reply back to client
//String reply = "World";
ZeroMqServerFactory.ZMQ_SERVER.send(objectSerialized);
//serverBusy = false;
}
try {
ZeroMqServerFactory.restartServer();
} catch (Exception e) {
ZeroMqServerFactory.stopServer();
}
}
I have a client like this:
private DocProduced sendMessage(String protocol, String ip, String port, int receiveTimeout, DocRequirement docRequirement) throws MessageSendingException {
String connectString = null;
try {
connectString = ConnectStringProducer.produceConnectString(protocol, ip, port);
} catch (ConnectionPropertyException e) {
throw new MessageSendingException(e);
}
String uniqueIdentity = identity.getUser().getLogin() + "_" + System.nanoTime();
byte[] objectSerialized = new byte[0];
try {
objectSerialized = ByteObjectManipulator.serialize(docRequirement);
} catch (IOException e) {
throw new MessageSendingException(e);
}
//init context
ZMQ.Context context = ZMQ.context(1);
// create request socket
ZMQ.Socket client = context.socket(ZMQ.REQ);
client.setIdentity(uniqueIdentity.getBytes());
client.setReceiveTimeOut(receiveTimeout);
client.connect(connectString);
//send object
client.send(objectSerialized);
//wait to receive
byte[] receivedByteArray;
try{
receivedByteArray = client.recv();
} catch (Exception e) {
client.close();
context.term();
throw new MessageSendingException(e);
}
if(receivedByteArray == null) {
client.close();
context.term();
throw new MessageSendingException("Received data null");
}
Object receivedObject;
try {
receivedObject = ByteObjectManipulator.deserialize(receivedByteArray);
} catch (IOException e) {
client.close();
context.term();
throw new MessageSendingException(e);
} catch (ClassNotFoundException e) {
client.close();
context.term();
throw new MessageSendingException(e);
}
if(!(receivedObject instanceof DocProduced)) {
client.close();
context.term();
throw new MessageSendingException("Wrong reply received from server");
}
//cast
DocProduced docProduced = (DocProduced) receivedObject;
client.close();
context.term();
return docProduced;
}
Now If i send three requests in a row, they are not getting received by the reply socket serially. most of the times i get 1,3,2 rather than 1,2,3. Is there any way to instruct the reply socket to reply in a fifo manner? please help.
Thanks in advance

StreamCorruptedException: invalid type code: 00

Server code:
while (true) {
Socket sock = serv.accept();
try {
new ClientSession(sock, outQueue, activeSessions);
System.out.println("CS");
} catch (IOException e) {
System.out.println("Sock error");
sock.close();
}
}
ClientSession:
class ClientSession extends Thread {
private Socket socket;
private OutboundMessages outQueue;
private ActiveSessions activeSessions;
private ObjectInputStream netIn;
private ObjectOutputStream netOut;
int n = 0;
boolean inGame = false;
boolean ready = false;
Player p;
public ClientSession(Socket s, OutboundMessages out, ActiveSessions as)
throws IOException {
socket = s;
outQueue = out;
activeSessions = as;
netOut = new ObjectOutputStream(socket.getOutputStream());
netOut.flush();
netIn = new ObjectInputStream(socket.getInputStream());
System.out.println("ClientSession " + this + " starts...");
while (true) {
Object nameMsg = null;
try {
nameMsg = netIn.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (nameMsg instanceof NameMessage) {
this.setName(((NameMessage) nameMsg).name);
break;
}
}
start();
}
public void run() {
try {
activeSessions.addSession(this);
while (true) {
Object inMsg = null;
try {
try {
inMsg = netIn.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
if (inMsg instanceof ReadyMessage) {
ready = true;
} else if (inMsg instanceof DirMessage) {
p.setDir(((DirMessage)inMsg).dir);
}
}
} finally {
try {
socket.close();
} catch (IOException e) {
}
}
}
public void sendMessage(Message msg) {
try {
if (!socket.isClosed()) {
netOut.writeObject(msg);
netOut.flush();
} else {
throw new IOException();
}
} catch (IOException eee) {
try {
socket.close();
} catch (IOException ee) {
}
}
}
Creating input and output on client side:
public void connect() {
try {
InetAddress serverAddr = InetAddress.getByName(serverName);
try {
System.out.println("Connecting with "
+ serverAddr.getHostName() + ":" + port);
socket = new Socket(serverAddr, port);
try {
System.out.println("Connected to "
+ serverAddr.getHostName());
netOut = new ObjectOutputStream(socket.getOutputStream());
netOut.flush();
netIn = new ObjectInputStream(socket.getInputStream());
netOut.writeObject(new NameMessage(name));
netOut.flush();
} finally {
}
} catch (ConnectException e) {
System.out.println("Cannot connect to server");
} catch (IOException e) {
System.out.println("Input error");
}
} catch (UnknownHostException e) {
System.out.println("Unknown server: " + e.getMessage());
}
}
receiver on client end:
public void run() {
while (true) {
Object a = null;
try {
a = netIn.readObject();
netIn.reset();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (a != null && a instanceof CoordMessage) {
setXY((CoordMessage)a);
}
}
}
Stacktrace:
java.io.StreamCorruptedException: invalid type code: 00
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at twoPlayerClient.Receiver.run(Receiver.java:28)
After creating input and output I keep passing them on to other classes and not creating new ones.
I have read other similar questions but can't find an answer to why this keeps happening.
new ClientSession(sock, outQueue, activeSessions);
I think, there is a new session for each client, and so you cannot use a stream variable, with global scope. Since its used by other session threads also.

Categories

Resources