Java sockets won't connect to server after some time - java

I have Java client which connects to my Java server. Java clients are in different networks and are running on MTX-GTW (Embedded Linux).
When I start server and the clients everything works fine, and clients are sending data every 1 minute. But after a day or more, clients will stop sending data one by one. Time varies.
But rest of the program runs fine, since program uses HTTP to communicate with some API and there we are still receiving data.
I checked server debug output and I can't see any errors or exceptions. I tried restarting the server and it also didn't help. My next step will be, to have similar client on my PC, so that I can see debug log, but that can take some time. So would any of you have any idea what could be the problem?
I use Java 7, here I call method to open socket:
static private void createHomeCallTimer()
{
new java.util.Timer().schedule(
new java.util.TimerTask()
{
public void run()
{
log.info("homeCall run");
Main main = new Main();
String data = "xxxxx";
try
{
log.info("Start of HOMECALL with data: " + data);
new TCPClient().openSocketAndSendData(data);
createHomeCallTimer();
} catch (Exception e)
{
log.error("Exception on homeCall: " + e);
createHomeCallTimer();
}
}
},
HOMECALLTIME
);
}
And this is client which is called by that method:
public class TCPClient
{
public void openSocketAndSendData(String data) throws IOException
{
Logger log = Logger.getLogger(TCPClient.class);
String ip = "xx.xx.xx.xx";
int port = 9000;
Socket clientSocket = new Socket(ip, port);
log.info("SOCKET TO IKU SERVER OPENED");
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
log.info("IKU SERVER: " + inFromServer.readLine());
outToServer.writeBytes(data);
clientSocket.close();
log.info("SOCKET CLOSED");
}
}

After you said that device has really small memory, then here's my suspect.
I didn't run your code but stripped it a little and speed it up to see what happens.
Here's code:
public class Main {
private static final int HOMECALLTIME = 10;
static private void createHomeCallTimer() {
new java.util.Timer().schedule(new java.util.TimerTask() {
public void run() {
// log.info("homeCall run");
// Main main = new Main();
String data = "xxxxx";
System.out.println(data);
// log.info("Start of HOMECALL with data: " + data);
// new TCPClient().openSocketAndSendData(data);
createHomeCallTimer();
}
}, HOMECALLTIME);
}
public static void main(String[] args) {
createHomeCallTimer();
}
}
And here's output after few minutes:
Exception in thread "Timer-21424" java.lang.OutOfMemoryError: unable
to create new native thread
at java.lang.Thread.start0(Native Method) at
java.lang.Thread.start(Thread.java:714) at
java.util.Timer.(Timer.java:160) at
java.util.Timer.(Timer.java:132) at
pkg.Main.createHomeCallTimer(Main.java:13) at
pkg.Main.access$0(Main.java:12) at pkg.Main$1.run(Main.java:22) at
java.util.TimerThread.mainLoop(Timer.java:555) at
java.util.TimerThread.run(Timer.java:505)
I suspect recursive call prevents freeing up memory and you run out of memory on your device. That's just a suspicion, but doesn't quite fit in a comment.
Here's the same code without recursion, using Timer:
static private void createHomeCallTimer() {
new java.util.Timer().scheduleAtFixedRate(new java.util.TimerTask() {
public void run() {
// log.info("homeCall run");
// Main main = new Main();
String data = "xxxxx";
System.out.println(data);
// log.info("Start of HOMECALL with data: " + data);
// new TCPClient().openSocketAndSendData(data);
}
}, 0, HOMECALLTIME);
}

Related

Socket Programming: The input stream gets corrupted without an exception

What I'm trying to achieve:
I'm trying to make a very simple camera surveillance system. In this case, the camera will be the server, and there will be a client application to watch the video feed on the other end.
For simplicity sake, I will emulate the camera by capturing frames from a saved video file, and sending these frames one by one through sockets to all the connected clients (Yes, the camera can handle more than one client). On the client side, I will receive the frames and then I will display them in a jPanel one after another to create the effect of a video playing.
I've already done all that but it works only for a couple of frames then it suddenly stops without an exception.
The Server-Side:
This is the main function in the Camera class:
public static void main(String[] args) throws InterruptedException, IOException, RemoteException, AlreadyBoundException {
ServerSocket ssock = new ServerSocket(1234);
System.out.println("Listening");
Camera.getInstance().startCamera(); // Starts reading the frames from the video file
while (true) {
Socket sock = ssock.accept();
System.out.println("Connected");
ClientConnection con = new ClientConnection(sock); // Creates a new connection
// Runs the connection on it's own thread
Thread conThread = new Thread(con);
conThread.start();
// Keeps a reference to the connection so it can be used later to send frames
Camera.getInstance().connections.add(con);
}
}
Snippets from the ClientConnection class:
The constructor:
public ClientConnection(Socket csocket) throws IOException {
this.csocket = csocket;
outStream = new PrintStream(csocket.getOutputStream());
objectOutStream = new ObjectOutputStream(csocket.getOutputStream());
}
The ClientConnection class implements the runnable interface so it can work on a separate thread. The run method will be responsible for receiving predefined messages (ex. "SET_MOVIE") from the client and do some actions accordingly. These actions and what they do are irrelevant to the question so we can safely ignore them. Here is the run method:
#Override
public void run() {
try {
inStream = new Scanner(csocket.getInputStream());
String msg;
while (inStream.hasNext()) {
msg = inStream.nextLine();
if (msg.equals("SET_MOVIE")) {
setMovie();
} else if (msg.equals("SET_IDLE")) {
setIdle();
} else if (msg.equals("FORCE_STATE_ON")) {
forceStateOn();
} else if (msg.equals("FORCE_STATE_OFF")) {
forceStateOff();
} else if (msg.equals("DISCONNECT")) {
// TO-DO
}
}
} catch (IOException ex) {
Logger.getLogger(ClientConnection.class.getName()).log(Level.SEVERE, null, ex);
}
}
This is the sendFrame method in the ClientConnection class. It gets called every time a new frame is available and ready to be sent.
// SEND_FRAME here works as an indicator to the client so that it can expect
// the image and start reading it
public void sendFrame(Frame _frame) throws IOException {
outStream.println("SEND_FRAME"); //tells the client there is a new frame
outStream.println(_frame.getCaptureTime()); //sends the time in which the frame was captured
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(_frame.getFrame(), "jpg", byteArrayOutputStream);
byte[] size = ByteBuffer.allocate(4).putInt(byteArrayOutputStream.size()).array();
outStream.write(size);
outStream.write(byteArrayOutputStream.toByteArray());
outStream.flush();
}
The Client-Side:
This is the main method, it simply creates a new CameraConnection and run it on it's own thread.
public static void main(String[] args) throws InterruptedException, IOException {
Thread client = new Thread(new CameraConnection("Cam_1", 1234));
client.start();
}
This is the CameraConnection constructor:
public CameraConnection(String name, int port) throws IOException {
this.name = name;
clientSocket = new Socket("localhost", port);
// This scanner will be used to read messages sent from the server
// such as "SEND_FRAME"
inStream_scanner = new Scanner(clientSocket.getInputStream());
// This inputStream will be used to read the bufferedImage in a array of bits
inStream = clientSocket.getInputStream();
// This is the outStream used to send messaages to the server
outStream = new PrintStream(clientSocket.getOutputStream());
}
This is the run method inside the CameraConnection:
#Override
public void run() {
String msg;
while (inStream_scanner.hasNext()) {
// Stores the incoming message and prints it
msg = inStream_scanner.nextLine();
System.out.println(msg);
// Irrelevant
if (msg.equals("NOTIFY_MOTION")) {
onMotion();
}
// Here is where the image gets read
else if (msg.equals("SEND_FRAME")) {
Frame f = new Frame();
long capturedTime = inStream_scanner.nextLong();
try {
byte[] sizeAr = new byte[4];
inStream.read(sizeAr);
int size = ByteBuffer.wrap(sizeAr).asIntBuffer().get();
byte[] imageAr = new byte[size];
inStream.read(imageAr);
BufferedImage image = null;
image = ImageIO.read(new ByteArrayInputStream(imageAr));
long receivedTime = System.currentTimeMillis();
// Prints out the image dimension and the time in which it was received
System.out.println("Received " + image.getHeight() + "x" + image.getWidth() + ": " + receivedTime);
f.setCaptureTime(capturedTime);
f.setFrame(image);
f.setRecievedTime(receivedTime);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}
The Output:
As mentioned above, it works fine for a couple of frames then it stops without an exception, also the scanner from the inputStream starts reading and printing weird symbols on the console as if it's corrupted. It keeps printing these weird symbols as long as the server keeps sending the frames. Here is an image to the output:
screenshot from the output
You can't mix two types of stream or reader or writer on the same socket. Buffering will foul you up completely. You need to use the object streams for everything.
You can't assume that read() fills the buffer.
For reading a 4-byte integer you should use readInt() (and writeInt() for writing it), not home-grown code.
For reading the body of the image you should use readFully().
I don't see any need for object streams here: you should use DataInputStream and DataOutputStream.

Java Sockets - Running the same client multiple times in parallel.

(Disclaimer that some of this code will be similar to online tutorials)
I think I've made it so that my server can handle multiple requests at once using threads, but I'm not entirely sure. And on top of that I don't know how I would actually send multiple requests at once.
My goal is to run my client code multiple times in parallel to see what happens if multiple clients connect to the server at the same time.
Client code (in separate project package):
Client clientSocket = new Client(9990,"localhost");
Socket socket = new Socket(clientSocket.host,clientSocket.portNumber);
clientSocket.performTask(socket);
("performTask(socket)" sends data to the server to perform a task)
Server code (separate project package from client code):
Server server = new Server(9990);
int clientNumber = 0;
ServerSocket socket = new ServerSocket(server.portNumber);
try {
while (true) {
new ServerHandler(socket.accept(),clientNumber).go();
clientNumber++;
}
}
finally {
socket.close();
}
}
ServerHandler class (same project package as server code):
public class ServerHandler extends Thread {
private static Socket socket;
private static int clientNumber;
public ServerHandler(Socket socket, int clientNumber) {
ServerHandler.socket = socket;
ServerHandler.clientNumber = clientNumber;
}
public void go() {
while(true) {
try {
//do calculation, do server tasks, etc.
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
So when the client connects to the server, the server implements the ServerHandler class to do the necessary calculations: the idea in doing that was so that multiple clients could connect all at the same time.
So my question is then in two parts:
(1) Have I set up my programs to allow for multi-threading, or have I made a mistake somewhere along the way? (e.g. someone told me I needed to use "Runnable" somewhere to use multi-threading, and I notice I haven't)
(2) After fixing my code to allow for multi-threading, how would I actually use it to let me run my client code in parallel?
Ok for starters, your ServerHandler extends the Thread class. Therefore to make it run as a seperate thread, always invoke by calling the start() method. You are calling you custom go method which will make the ServerHandler execute in the same thread as your infinite while loop. So it should be something like this ServerHandler(socket.accept(),clientNumber).start(). Also it is always better to implement Runnable because java does not support multiple inheritance via the "extends" concept. Therefore in the future if your ServerHandler needs to actually extend a custom class, it wont be able to since it already extends the Thread class. Its better to implement interfaces since there is no limit as to how many you can implement.
Hence implementing the Runnable interface is a good design choice. You can run your client code in parallel by making the client into a threaded model. Here is one such example of multiple client sockets connecting to the server in parallel
Server Code
public class WebServer {
static int hitCount = 0;
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(7777, 10000);
while (true) {
Socket defaultSocket = serverSocket.accept();
new Thread(new ServerSlave(defaultSocket)).start();
System.out.println("Size is :" + hitCount);
}
}
}
class ServerSlave implements Runnable {
Socket clientSocket;
public ServerSlave(Socket socket) {
clientSocket = socket;
WebServer.hitCount++;
}
public void run() {
try {
DataInputStream inputStream = new DataInputStream(clientSocket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
System.out.println(inputStream.readUTF());
outputStream.writeUTF("Thank you for contacting the web server");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Client Code :
public class Client {
static int excepCount=0;
public static void main(String[] args) throws Exception {
for (int i = 0; i < 100; i++) {
new Thread(new Worker("" + i)).start();
}
Thread.sleep(10000);
System.out.println( Client.excepCount);
}
}
class Worker implements Runnable {
String clientName;
public Worker(String name) {
clientName = name;
}
public void run() {
System.out.println("Process started for : " + clientName);
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 7777);
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF("Hello socket. Client number " + clientName + "here");
InputStream inFromServer = socket.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
System.out.println("Closing socket");
} catch (IOException e) {
Client.excepCount++;
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
You should use multithreading .
You have to rename method to "run"/ and call that method using "start".Please change Server side code to
try {
while (true) {
new ServerHandler(socket.accept(),clientNumber).start();
clientNumber++;
}
}
finally {
socket.close();
}
and client side
public class ServerHandler extends Thread {
private static Socket socket;
private static int clientNumber;
public ServerHandler(Socket socket, int clientNumber) {
ServerHandler.socket = socket;
ServerHandler.clientNumber = clientNumber;
}
public void run() {
while(true) {
try {
//do calculation, do server tasks, etc.
}
} catch (IOException e) {
e.printStackTrace();
}
}

java server using jframe

i'm making GUI for my java server program but when i launch it program show white JFrame and doesn't load component into frame.
Here there's code:
public ServerFrame() throws SQLException, ClassNotFoundException, IOException {
initComponents();
server = new ServerSocket(4444);
textList.setText("Waiting for client to connect...");
SimpleDataSource.init("database.properties");
net = new Network();
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
ServerFrame sf;
try{
sf = new ServerFrame();
sf.setVisible(true);
s = server.accept();
InetAddress clientAddress = s.getInetAddress();
textList.setText("Incoming connection from: " + clientAddress.getHostName() + "[" + clientAddress.getHostAddress() + "]\n");
ServiceClass service = new ServiceClass(s,net);
Thread t = new Thread(service);
t.start();
}catch (SQLException | ClassNotFoundException | IOException ex){
Logger.getLogger(ServerFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
when program launch it doesn't show me component into frame because it wait client to connect. When a client connect it shows correctly all components..how can i show all component without client connected?
thanks
I do not know what these lines do exactly, so that happens below might also apply to them.
SimpleDataSource.init("database.properties");
net = new Network();
The main problem is most likely that this line: server = new ServerSocket(4444); hangs everything until the client connects, which makes the main thread of your application continue execution and thus display everything.
To fix this, launch the server on a seperate Thread.
Something like so:
new Thread(new Runnable()
{
#Override
public void run()
{
server = new ServerSocket(4444);
}
}).start();
You will need to declare your server final, so that it can be accessed from within the run method.

MultiThreaded Server, which is a client to another server

I'm using a server socket to accept clients on the main thread, when a thread is accepted,the clients socket is given to a handler which is started in a new thread to process communications. However, before I start running my server to access clients, it connects to a second server which it must list to and be able to respond to and pass on the messages it gets to it's clients.
Hopefully this image illustrate what I mean:
The small server must be continuously listening for input from the big server, and also able to output responses.
//Default constructor
private smallServer(){}
//method to initialise and start the server
public static void StartServer(int port) throws IOException {
smallServer ss = new smallServer();
ss.bs= new bigServerClient(ss);
Thread nsc_Thread = new Thread(ss.bsc);
bsc_Thread.start();
//accepts clients and starts new thread for them
ss.ServerRun(port);
}
private void ServerRun(int port) throws IOException {
ServerSocket server = new ServerSocket(port);
server.setSoTimeout(50);
while (run) {
Socket client = null;
try {
client = server.accept();
} catch (SocketTimeoutException e) {
}
if (client != null) {
ClientHandler handler = new ClientHandler(client, this);
Thread handleThread = new Thread(handler);
handleThread.start();
}
}
if (!run) {
synchronized (ClientHandler.handlers) {
for (ClientHandler handler : ClientHandler.handlers) {
handler.terminateHandler();
}
}
System.exit(0);
}
}
public void processBigServerCommand(String toProcess) {
System.out.println("RESEAVED: " + toProcess);
}
The big server client(on the small server) then does this:
public class bigServerClient implements Runnable {
private smalsServer ss;
private PrintWriter printer;
private BufferedReader reader;
private Socket socket;
public bigServerClient(smallServer _ss) throws IOException {
ss = _ss;
socket = new Socket("Localhost", 5000);
printer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
printer.flush();
SendBigServerMessage("Starting String");
}
private void SendBigServerMessage(String toSend) {
printer.print(toSend);
printer.flush();
}
#Override
public void run() {
try {
while (ss.state()) {
String inputLine;
while ((inputLine = reader.readLine()) != null) {
ss.processBigServerCommand(inputLine);
System.out.println(inputLine);
}
}
} catch (IOException e) {
} finally {
try {
socket.close();
} catch (IOException ex) {
}
}
}
}
From what's above, can anyone see why the big server client isn't responding to the big server when a message is sent? I'm guessing it's something to do with the main thread blocking the second thread, but I'm not sure... Any help would be greatly appreciated.
You lost me in your code...
Simplify it.
Your smallServer (see class names conventions) should have persistent connection to BigServer (effectively it is BigServer client) - you can implement it in your smallServer class, it should connect (once) and open I/O to BigServer (once) and close everything once the connection is terminated.
As your smallServer will handle multiple clients and pass their requests to BigServer there is no guarantee of the order of BigServer responses - you should do something to handle that (maybe pass UUID with requests?)
Simplify your smallServer and make sure that it runs...

send a file to a client after long wait

i've a java servlet that makes some reports. When a user choose a report it makes a query on a db and stream the xls report to the client. All in synchronous way. The problem is that sometimes i've a lot of records to fetch from the db and i would like to give a better user experience, allowing the user to do something else while the report is processing and popping out in some way the link when the process is finished. Is there a java library or some techniques to avoid the long waiting and achieve that goal?
Right now i've prepared a piece of code that in a asynchronous way completes the report and sends an email to the registered client, with the url from wich download the file, but it has to be replaced with something else because i can no longer communicate by email.
Thanks in advance
heres my take on this, i dont know of a single library that will exactly match you needs, youd probably need some custom development here.
I believe you have implemented async service that on completion sends
out an email for notification. Instead of sending out an email, let
that thread update a job table of some sort -- an entry in a db table
or some application/session scoped map.
Have a servlet/restful ws
expose that job table at some url. Poll the url at regular
intervals. Ajax poll is a standard feature in js libraries JQuery,
Prototype.
When you get a response that some report is complete, show
some popup or may be a facebook you-have-notification kind of thing
on the client side.
i have not considered authentication/authorization issues here, you need to take care of that as well.
Hope this helps
A multithreaded client server program to download my image files.
Since there are four files to download the client makes 4 connection attempts. This is not limited to 4 but the files sent by the FileServer will get repeated after the fourth attempt. The save dialog and file saving is done in different threads so as to not hamper the file downloading.
Here is the FileServer...
public class FileServer {
private final ExecutorService exec = Executors.newCachedThreadPool();
final String[] fileNames = {
"C:\\Users\\clobo\\Pictures\\Arpeggios\\Ex 1.jpg",
"C:\\Users\\clobo\\Pictures\\Arpeggios\\Ex 2.jpg",
"C:\\Users\\clobo\\Pictures\\Arpeggios\\Ex 3.jpg",
"C:\\Users\\clobo\\Pictures\\Arpeggios\\Ex 4.jpg"
};
public void start() throws IOException {
ServerSocket socket = new ServerSocket(7777);
System.out.println("Waiting for client message...");
while (!exec.isShutdown()) {
try {
for (final String fileName : fileNames){
final Socket conn = socket.accept();
exec.execute(new Runnable() {
public void run() {
sendFile(conn,fileName);
}
});
}
} catch (RejectedExecutionException e) {
if (!exec.isShutdown())
log("task submission rejected", e);
}
}
}
public void stop() {
System.out.println("Shutting down server...");
exec.shutdown();
}
private void log(String msg, Exception e) {
Logger.getAnonymousLogger().log(Level.WARNING, msg, e);
}
public void sendFile(Socket conn, String fileName) {
File myFile = new File(fileName);
if (!myFile.exists()) {
log("File does not exist!",null);
}
// file does exist
System.out.println(Thread.currentThread().getName());
System.out.println("AbsolutePath:" + myFile.getAbsolutePath());
System.out.println("length: " + myFile.length());
if (myFile.exists()) {
try {
ObjectOutputStream oos = new ObjectOutputStream(
conn.getOutputStream());
oos.writeObject(myFile);
oos.close();
} catch (IOException e) {
log("IOException Error", e);
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
FileServer fs = new FileServer();
fs.start();
}
}
here is the FileServerClient...
public class FileServerClient {
private final ExecutorService exec = Executors.newCachedThreadPool();
Frame myFrame = new Frame();
List<File> fileList = new ArrayList<File>();
public void receiveFileFromServer() throws Exception{
Socket sock = null;
InputStream socketInputStream = null;
String host = "localhost";
int port = 7777;
for (int i=0;i<4;i++) {
sock = new Socket(host, port);
socketInputStream = sock.getInputStream();
System.out.println("Connection successful...");
// recieve the file
ObjectInputStream ois = new ObjectInputStream(socketInputStream);
// file from server is deserialized
final File myfile = (File) ois.readObject();
fileList.add(myfile);
// deserialized file properties
System.out.println("AbsolutePath: " + myfile.getAbsolutePath());
System.out.println("FileName:" + myfile.getName());
System.out.println("length" + myfile.length());
exec.execute(new Runnable() {
public void run() {
saveFile(myfile);
}
});
}
}
private void saveFile(File myfile) {
FileDialog fileDialog = new FileDialog(myFrame,
"Choose Destination for "+ myfile.getName(), FileDialog.SAVE);
fileDialog.setDirectory(null);
fileDialog.setFile("enter file name here");
fileDialog.setVisible(true);
String targetFileName = fileDialog.getDirectory()
+ fileDialog.getFile() + ".jpg";
System.out.println("File will be saved to: " + targetFileName);
copyBytes(myfile, targetFileName);
}
private void copyBytes(File originalFile, String targetFileName) {
try {
FileInputStream in = new FileInputStream(originalFile);
FileOutputStream out = new FileOutputStream(targetFileName);
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
out.close();
in.close();
} catch (Exception e) {
log("IOException Error", e);
}
}
private void log(String msg, Exception e) {
Logger.getAnonymousLogger().log(Level.WARNING, msg, e);
}
public static void main(String[] args) throws Exception {
FileServerClient client = new FileServerClient();
client.receiveFileFromServer();
}
}
You could make an asynchronous request from the client. Lets assume that you client is an html page. When the user selects a report and clicks on 'submit' you could fire an ajax request with the report parameters (jquery can be useful for this). It would be good to keep a section on the user homepage that says something like 'prepared reports'. The client can then goto the prepared report section to download the report. As specified in the comments above, you may also have to implement a popup that informs the user that the requested report is ready. the popup is shown when the ajax requests returns successfully. However, the client may have logged out by the time the report finishes, so it may be a good idea to make the download link available again in the 'prepared reports' section when the user logs in.

Categories