This is my Socket test program.
My problem is that when I execute the code below. After I call read() on Socket InputStream for first time, it block as expected.
But when loop go back to read() again, it never blocks on read() again? Thus it ends up with a tight and endless loop.
What should I do if I want to use separate thread to get server response? Is there any design pattern for this requirements?
package test.socket;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class TestMario {
private InputStream in;
private OutputStream out;
public static void main(String[] args) throws Exception {
new TestMario().go();
}
public TestMario() {
try {
Socket echoSocket = new Socket("xxx.xxx.xxx.xxx", 1234);
in = echoSocket.getInputStream();
out = echoSocket.getOutputStream();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void go() throws UnknownHostException, IOException {
Thread writer = new Thread(new Runnable() {
public void run() {
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(out);
String userInput;
try {
System.out.print("input your command:");
while ((userInput = stdIn.readLine()) != null) {
System.out.println("you type:" + userInput);
writer.print(userInput);
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
Thread reader = new Thread(new Runnable() {
StringBuffer sb = new StringBuffer();
public void run() {
while (true) {
System.out.println("waiting for server response...");
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] content = new byte[512];
int bytesRead = -1;
while((bytesRead = in.read(content)) != -1) { // read() doesn't block anymore after first read
baos.write(content, 0, bytesRead);
} // while
System.out.println("got:" + new String(baos.toByteArray()));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
});
writer.start();
reader.start();
System.out.println();
}
}
This means that it either returns -1 or throws IOException. You implemented 2 loops: the internal loop verifies that value returned by read and exits if value is -1. This is fine. However the outer loop while(true) makes you to enter the read again and again, so it is not blocked anymore because the end of stream is achieved.
EDIT: credits to #assylias that wrote comment that hints this.
Related
I am trying to write a test for the writeMessage() method. But I have no idea how to start, since I need to test an OutputStream. This should be something like a small chat. It should read a message from console, write it to the text file and than print all messages that have been written to the file.
This is for a university project.
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
public class ChatIntImplement implements ChatI {
public static String readMessage() throws IOException, NullPointerException{
InputStream is = System.in;
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = null;
try {
message = br.readLine();
}catch(IOException ex) {
System.err.println("couldn't write data (fatal)");
System.exit(0);
}
return message;
}
public static void messageToFile(String message) throws IOException {
try {
String filename = "savedMessage.txt";
OutputStream os = new FileOutputStream(filename, true);
PrintStream ps = new PrintStream(os);
ps.println(message);
}catch (FileNotFoundException ex) {
System.err.println("couldn't open file - fatal");
System.exit(0);
}
}
public static void showMessages() {
InputStream is = null;
try {
is = new FileInputStream("savedMessage.txt");
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message;
while((message = br.readLine())!= null) {
System.out.println(message);
}
}catch(FileNotFoundException ex) {
System.err.println("couln't open file -fatal");
System.exit(0);
}catch(IOException e) {
System.err.println("couldn't read data (fatal)");
System.exit(0);
}
}
#Override
public void writeMessage(String message){
try {
messageToFile(message);
showMessages();
}catch (IOException e) {
System.err.println("couldn't write data (fatal");
System.exit(0);
}
}
#Override
public void exit() {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
ChatIntImplement chat = new ChatIntImplement();
try {
String message = readMessage();
chat.writeMessage(message);
}catch (IOException e) {
System.err.println("couldn't write data (fatal");
System.exit(0);
}catch (NullPointerException npe) {
System.err.println("Du hast nichts eingegeben");
System.exit(0);
}
}
}
I think the problem you are having getting started is because of how you have structured your class. All of your methods are static, and each method's dependencies, such as the various input and output streams you are using, are created as needed inside each method. For instance, in your messageToFile(...) method:
OutputStream os = new FileOutputStream(filename, true);
A much better approach to your project would be design your class using a traditional object-oriented class design that makes use of a pattern called Dependency Injection
The idea here is that your class that implements your ChatI interface would use member-variables for your input and output streams and the other objects, which would be initialized in the constructor for the class. Then you could control, and most importantly, get access to those streams from within your unit tests - something like this perhaps:
#Test
public void givenAMessageString_When() {
String expectedInput="expectedString";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ChatIntImplement chat = new ChatIntImplement(baos);
...
chat.writeMessage(expectedInput);
string output = new String(baos.toByteArray());
assertThat(output).equals(expectedInput);
}
I'm trying to develop a simple Java file transfer application using TCP.
My current server code is as follows:
package tcp.ftp;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class FTPServer {
public static void main(String[] args) {
new FTPServer().go();
}
void go() {
try {
ServerSocket server = new ServerSocket(2015);
System.out.println("server is running ....!");
while (true) {
Socket socket = server.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String file = reader.readLine();
System.out.println("file to be downloaded is : " + file);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
//bos.close();
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
Using my current server code above, the downlloding does not work as expected. the above code sends part of the file to the client , not the entire file. Note that I used the flush method to flush the buffer. but when I replace the flush () method by the close () method, the file is fully sent to the client whithout any loss. Could anyone please explain this behavior!
UPDATE: Here is the code of my client:
package tcp.ftp;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
*
* #author aaa
*/
public class FTPClient {
public static void main(String[] args) {
String file = "JasperReports-Ultimate-Guide-3.pdf";
try {
InetAddress address = InetAddress.getLocalHost();
Socket socket = new Socket(address, 2015);
System.out.println("connection successfully established ....!");
PrintWriter pw = new PrintWriter(socket.getOutputStream());
pw.println(file);
pw.flush();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy" + file));
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
System.out.println("file download is complete ...!");
} catch (UnknownHostException ex) {
System.out.println(ex.getMessage());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
Another behavior without the use of Socket. take the following code that copy a file from a source to a destination:
public class CopieFile {
static void fastCopy(String source, String destination) {
try {
FileInputStream fis = new FileInputStream(source);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(destination);
BufferedOutputStream bos = new BufferedOutputStream(fos);
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
} catch (FileNotFoundException ex) {
System.out.println(ex.getMessage());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
public static void main(String[] args) throws IOException {
String source = "...";
String destination = "...";
fastCopy(source, destination);
}// end main
}// end class
the above code to copy a file from one location to another without any loss. Note well that I did not close the stream.
If you never close the stream the client wil never get end of stream so it will never exit the read loop.
In any case the stream and the socket are about to go out of scope, so if you don't close them you have a resource leak.
I want to made a Server Which makes a client and start conversation with him but IOException is occur in Handler's code I couldn't underStand why Br.readLine method throws Exception
Here is code of mine Server project's package's classess and two clients abc, def classes are also
This is code of Server projects classeess...............
package server;
import java.io.IOException;
import java.net.ServerSocket;
public class Server {
private void operate() {
try {
ServerSocket serverSocket = new ServerSocket(2222);
while(true) new Thread(new Handler(serverSocket.accept())).start();
} catch(IOException e){
System.out.println("IOException in operate method of Server");
}
}
public static void main(String[] args) {
new Server().operate();
}
}
package server;
import java.io.*;
import java.net.Socket;
public class Handler implements Runnable {
Handler(Socket s) {
socket = s;
counter++;
}
public void run() {
try {
while(true) System.out.println(new BufferedReader(new InputStreamReader(socket.getInputStream())).readLine()); //This throw the IOExceptionnnnnnnnnnnnnnnnnnnnn...............
} catch(IOException e) {
System.out.println("IOException in "+counter+"'s run method");
}
}
private final Socket socket;
private static int counter =0;
}
Code of First Client ABC...........................
package abc;
import java.net.Socket;
import java.io.*;
public class Abc {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost",2222);
while(true) new PrintWriter(socket.getOutputStream()).println("HI from Abc");
} catch(IOException e) {
System.out.println("IOException in main ");
}
}
}
Code of Another Client DEf.........................
package def;
import java.io.*;
import java.net.Socket;
public class DEf {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost",2222);
while(true) new PrintWriter(socket.getOutputStream()).println("HI from Abc");
} catch(IOException e) {
System.out.println("IOException in main ");
}
}
}
Your clients request the output stream repeatedly from the socket using socket.getOutputStream(). Instead, you should invoke this method and create a corresponding writer only once, for example:
Socket socket = new Socket("localhost",2222);
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while(true) {
writer.println("HI from Abc");
...
}
Same with the Handler class - create your buffered reader once.
I have already posted answers on Server-Client Socket Communication. Please have a look.
Java Server with Multiclient communication.
Basic echo server, client-server relationship
Try this code. It might solve you problem.
Handler.java:
Check BufferedReader.ready() before BufferedReader.readLine()
Use single BufferedReader
class Handler implements Runnable {
private BufferedReader reader;
Handler(Socket s) {
socket = s;
counter++;
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
try {
while (socket.isConnected() && !socket.isClosed()) {
if(!reader.ready()){
continue;
}
//System.out.println("ready");
System.out.println(reader.readLine()); // This throw
// the
} // IOExceptionnnnnnnnnnnnnnnnnnnnn...............
} catch (Exception e) {
e.printStackTrace();
System.out.println("IOException in " + counter + "'s run method");
}
}
private final Socket socket;
private static int counter = 0;
}
Abc.java:
Use single PrintWriter
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while (true)
writer.println("HI from Abc");
DEf.java:
Use single PrintWriter
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while (true)
writer.println("HI from Abc");
I have a Client-Server programm. The Client-programm sends a file to the server and the server receives the file. my problem is, that the file is not really receiving on the server...I't creates a file.txt in the server-directory, but it is empty...(yes i'm sure that ne file.txt in the client-directory is not empty ;) )
I think the problem is the while-loop in Client.java, because it is never embarrassed....
For the future i implements now on the server side one thread per receiving file.
The client-programm:
package controller;
public class Main {
public static void main(String[] args) {
new Controller();
}
}
-
package controller;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Controller {
public Controller() {
try {
sendFileToServer();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendFileToServer() throws UnknownHostException, IOException {
Socket socket = null;
String host = "localhost";
socket = new Socket(host, 5555);
String filename = "file.txt";
File file = new File(filename);
OutputStream outText = socket.getOutputStream();
PrintStream outTextP = new PrintStream(outText);
outTextP.println(filename);
long filesize = file.length();
byte[] bytes = new byte[(int) filesize];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
int count;
System.out.println("Start sending file...");
while ((count = bis.read(bytes)) > 0) {
System.out.println("count: " + count);
out.write(bytes, 0, count);
}
System.out.println("Finish!");
out.flush();
out.close();
fis.close();
bis.close();
socket.close();
}
}
-
The server-programm:
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
new Server();
}
}
-
public class Server {
private ServerSocket serverSocket;
public Server() {
try {
serverSocket = new ServerSocket(5555);
waitForClient();
} catch (IOException e) {
e.printStackTrace();
}
}
private void waitForClient() {
Socket socket = null;
try {
while(true) {
socket = serverSocket.accept();
Thread thread = new Thread(new Client(socket));
thread.start();
}
} catch (IOException ex) {
System.out.println("serverSocket.accept() failed!");
}
}
}
-
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class Client implements Runnable{
private Socket socket;
public Client(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
receiveFile();
}
private void receiveFile() {
try {
InputStream is = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
int bufferSize = 0;
InputStream outText = socket.getInputStream();
// Get filename
InputStreamReader outTextI = new InputStreamReader(outText);
BufferedReader inTextB = new BufferedReader(outTextI);
String dateiname = inTextB.readLine();
System.out.println("Dateiname: " + dateiname);
try {
is = socket.getInputStream();
bufferSize = socket.getReceiveBufferSize();
System.out.println("Buffer size: " + bufferSize);
} catch (IOException ex) {
System.out.println("Can't get socket input stream. ");
}
try {
fos = new FileOutputStream(dateiname);
bos = new BufferedOutputStream(fos);
} catch (FileNotFoundException ex) {
System.out.println("File not found.");
}
byte[] bytes = new byte[bufferSize];
int count;
while ((count = is.read(bytes)) > 0) {
bos.write(bytes, 0, count);
System.out.println("This is never shown!!!"); // In this while-loop the file is normally receiving and written to the directory. But this loop is never embarrassed...
}
bos.flush();
bos.close();
is.close();
socket.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
When you do these kind of transfers you have to keep in mind that there is a difference between a socket's close and shutdown, in your code you close the socket in the client.
So lets see what happens : you fill in the buffers then you tell the socket to close which will discard the operation you just asked for.
When you shutdown you tell the socket "I won't send more data but send what's left to be sent and shut down" so what you need to do is to shut down the socket before you close it so the data will arrive.
So instead of this
out.flush();
out.close();
fis.close();
bis.close();
socket.close();
Try it with this
out.flush();
socket.shutdownInput(); // since you only send you may not need to call this
socket.shutdownOutput(); // with this you ensure that the data you "buffered" is sent
socket.close();
Generally if you want a graceful close, you should do it like this in all cases even for the server, so what you did is usually okay if there is an error and you just close the connection since you cant recover from an error.
i'm making a program/game that will update automatically. i have the update part down, but not the checking of the version. i would have thought that it'd be pretty easy. heres what i've done. i wrote an updater for the game, and i wrote a server. the server starts a thread every time a client/updater connects. the thread handles everything. the game updater reads a file called version.txt and that provides the version number (default 0.0.1) and sends it to the server. the server does recieve the version, and will System.out.println(); if the version matches, and if i change the version, it changes the output. so that part works. but that is as far as it goes. the second part of the process is that the server then sends just a text file called NPS Game.txt (it sends anything, but txt was easy to test with) and the client replaces the old version of this file with the new one that just sent. the problem is that i keep getting an error that says the Socket is closed. i've tried using socket.setKeepAlive(true); but that didnt change anything (i put that on both the client and the server). here is the code:
server:
package main;
import java.io.*;
import java.net.*;
import javax.swing.JOptionPane;
public class Server {
static ServerSocket serverSocket = null;
static Socket clientSocket = null;
static boolean listening = true;
public static void main(String[] args) throws IOException {
try {
serverSocket = new ServerSocket(6987);
} catch (IOException e) {
ServerThread.showmsg("Could not use port: 6987");
System.exit(-1);
}
ServerThread.showmsg("server- initialized");
ServerThread.showmsg("server- waiting...");
while (listening)
new ServerThread(serverSocket.accept()).start();
}
}
server thread:
package main;
import java.io.*;
import java.net.Socket;
import java.net.SocketException;
import javax.swing.JOptionPane;
public class ServerThread extends Thread {
Socket socket;
ObjectInputStream in;
ObjectOutputStream out;
String version = "0.0.1";
public ServerThread(Socket socket) {
super("Server Thread");
this.socket = socket;
}
public void run() {
showmsg("server- Accepted connection : " + socket);
getVersion();
sendFile();
}
public void getVersion() {
try {
ObjectInputStream ois = new ObjectInputStream(
socket.getInputStream());
try {
String s = (String) ois.readObject();
if (s.equals(version)) {
System.out.println("server- matched version :)");
} else {
System.out.println("server- didnt match version :(");
System.exit(0);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendFile() {
// sendfile
File myFile = new File("C:\\Programming\\NPS\\Files\\bin\\NPS Game.txt");
byte[] mybytearray = new byte[(int) myFile.length()];
FileInputStream fis;
try {
fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray, 0, mybytearray.length);
OutputStream os = socket.getOutputStream();
showmsg("server- Sending...");
os.write(mybytearray, 0, mybytearray.length);
os.flush();
socket.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void showmsg(String s) {
JOptionPane.showMessageDialog(null, s);
}
}
and the client/updater:
package main;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JOptionPane;
import org.omg.CORBA.portable.InputStream;
public class Connections {
String IP, port;
String message = "";
Socket socket;
public Connections(boolean server, boolean updating, String IP, String port) {
this.IP = IP;
this.port = port;
try {
socket = new Socket(IP, Integer.parseInt(port));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (!server) {
if (updating) {
try {
sendVersion();
updating();
} catch (IOException e) {
e.printStackTrace();
}
} else {
client();
}
}
if (server) {
}
}
public void sendVersion() throws IOException {
FileReader fileReader = new FileReader(
"C:\\Program Files\\AVTECH\\NPS\\Files\\bin\\version.txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
String stringRead = bufferedReader.readLine();
bufferedReader.close();
ObjectOutputStream oos = new ObjectOutputStream(
socket.getOutputStream());
oos.writeObject(stringRead);
oos.flush();
oos.close();
}
public void updating() throws IOException {
int filesize = 6022386; // filesize temporary hardcoded
int bytesRead;
int current = 0;
showmsg("client- connected");
// receive file
byte[] byteArray = new byte[filesize];
java.io.InputStream inStream = socket.getInputStream();
FileOutputStream fileOutStream = new FileOutputStream(
"C:\\Program Files\\AVTECH\\NPS\\Files\\bin\\NPS Game.txt");
BufferedOutputStream buffOutStream = new BufferedOutputStream(
fileOutStream);
bytesRead = inStream.read(byteArray, 0, byteArray.length);
current = bytesRead;
do {
bytesRead = inStream.read(byteArray, current,
(byteArray.length - current));
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
buffOutStream.write(byteArray, 0, current);
buffOutStream.flush();
buffOutStream.close();
inStream.close();
socket.close();
}
public static void showmsg(String s) {
JOptionPane.showMessageDialog(null, s);
}
}
i dont know what's wrong with it, but it is really frusturating. if anyone can help, it would be appreciated. some things ive done: google all kinds of questions, tried implementing socket.setKeepAlive(true);. also, i thought it might be of note, in the server thread, right above the line BufferedInputStream bis = new BufferedInputStream(fis);, i put System.out.println(socket.isClosed); and it returned true. thats all i have. thanks in advance!
I think that closing one of both streams, closes the socket. So try to remove the ois.close() call out of your getVersion() method at the server side. Also get rid of the oos.close() call in your sendVersion() method at the client side.
When you construct an ObjectOutputStream or ObjectInputStream and you are done with it, you shouldn't close that stream, because it will close the underlying stream, which is in your case the socket.