Code below works and sends message at scheduled time but I think it isn't a good solution to open new socket every time timer executes scheduled task. What I would like is to open socket in run method only once and access it in SendMessage class whenever new instance of class is made in timer. That way it doesn't work, it only sends one message and then stops sending. Also I would be happy for some critics about code or tips for making it thread safe.
public class Client implements Runnable{
// Client Constructor here
@Override
public void run(){
//SENDS ONLY ONE MESSAGE
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
Timer timer = new Timer();
timer.schedule(new SendMessage(), 0, 1000/mps);
}
private class SendMessage extends TimerTask{
private int id;
@Override
public void run() {
try
{ // THIS WORKS FINE, SENDS MESSAGES AT SCHEDULED TIME
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
OutputStream outToServer = pitcherSocket.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeInt(id);
out.flush();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
EDIT: WHOLE CODE
CLIENT
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class Pitcher implements Runnable{
private int port;
private int mps;
private int size;
private String hostname;
private List<Integer> messageIds = Collections.synchronizedList(new ArrayList<Integer>());
private Socket pitcherSocket;
//constatns, integer is 4 bytes, long is 8 bytes
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public Pitcher(int port, int mps, int size, String hostname) {
this.port = port;
this.mps = mps;
this.size = size;
this.hostname = hostname;
}
@Override
public void run(){
System.out.println("Pitcher running...");
System.out.println();
Timer timer = new Timer();
timer.schedule(new SendMessage(), 0, 1000/mps);
timer.schedule(new DisplayStatistics(), 0, 1000/mps);
}
//Nested class that sends messages
private class SendMessage extends TimerTask{
private int numberOfSentMessages = 0;
private int id;
@Override
public void run() {
try {
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
OutputStream outToServer = pitcherSocket.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
//send message size
out.writeInt(size);
//message id is same as number of the sent message
id = numberOfSentMessages + 1;
out.writeInt(id);
messageIds.add(id);
//get system timestamp
long currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest-
byte[] rest = new byte[size - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytse) - timestamp(8 bytes)
out.write(rest);
out.flush();
numberOfSentMessages++;
InputStream inFromServer = pitcherSocket.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
Integer catcherMessageSize = in.readInt();
Integer catcherId = in.readInt();
long catcherTimestamp = in.readLong();
System.out.println("Sent message: " + size + " " + id + " " + currentTimestamp + "...");
System.out.println("Received message: " + catcherMessageSize + " " + catcherId + " " + catcherTimestamp + "...");
System.out.println();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
SERVER
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class Catcher implements Runnable{
private int port;
private String bind;
private ServerSocket serverSocket;
//constatns, integer is 4 bytes, long is 8 bytes
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public Catcher(int port, String bind) {
this.port = port;
this.bind = bind;
}
@Override
public void run() {
System.out.println("Catcher running...");
System.out.println();
try {
serverSocket = new ServerSocket(port, 100, InetAddress.getByName(bind));
}
catch (IOException e1) {
e1.printStackTrace();
}
while(true){
try
{
Socket server = serverSocket.accept();
DataInputStream in = new DataInputStream(server.getInputStream());
Integer pitcherMessageSize = in.readInt();
Integer pitcherId = in.readInt();
long pitcherTimestamp = in.readLong();
DataOutputStream out = new DataOutputStream(server.getOutputStream());
//message id and size are sent back
out.writeInt(pitcherMessageSize);
out.writeInt(pitcherId);
//send back current time
long currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest
byte[] rest = new byte[pitcherMessageSize - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytes) - timestamp(8 bytes)
out.write(rest);
out.flush();
System.out.println("Received message: " + pitcherMessageSize + " " + pitcherId + " " + pitcherTimestamp + "...");
System.out.println("Sent message: " + pitcherMessageSize + " " + pitcherId + " " + currentTimestamp + "...");
System.out.println();
//server.close();
}
catch(SocketTimeoutException s){
System.out.println("Socket timed out!");
break;
}
catch(IOException e){
e.printStackTrace();
break;
}
}
}
}