Here I am creating a thread to check for a server response every 2 seconds, the issue is that the client.monitorResponse() is a readLine() method and will not continue until a response is received.
client = new ClientObject("localhost");
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
try {
String response = null;
if(!(response = client.monitorResponse()).isEmpty()) {
System.out.println("Response: " + response);
} catch (Exception e) {
e.printStackTrace();
}
}
}, 2000, 2000);
I am sending the response via the Server like so (where client is a established Socket):
public SocketObject(Socket client, int numberOfClients) throws Exception {
socket = client; // the .accept() socket is passed through
// this is because I assign them ID's for later use (I hold an ArrayList of sockets)
this.clientId = numberOfClients;
// both these are static to the class
outputStream = new PrintWriter(client.getOutputStream());
inputStream = new BufferedReader(new InputStreamReader(client.getInputStream()));
}
public void sendResponse(String response) {
outputStream.println(response);
}
I am then picking the response up via the client Socket that has connected to the server:
public ClientObject(String hostname) throws IOException {
// socket is static to this class
socket = new Socket(hostname, 4444);
System.out.println("Connected to " + hostname + " on port 4444...");
// both static to this class
outputStream = new PrintWriter(socket.getOutputStream(), true);
inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Successfully started a stream on " + hostname);
this.hostname = hostname;
}
public String monitorResponse() throws Exception {
System.out.println("Listening for a response...");
return inputStream.readLine();
}
The debug console only displays the Listening for a response... output once which is telling me that it doesn't get past the inputStream.readLine() method in-side the Thread. Is there anyway I can add a timeout on the BufferedReader? I have tried multiple solutions like adding a .setSoTimeout() to the socket before creating the BufferedReader but all that did was close the connection/socket after the specified time.
Any help would be appreciated.
You should use a non-blocking (NIO) request and read chunks looking for newlines in-between. Typically in Java you just have to look for the NIO version of the Stream class you are using and use it to check every N seconds for new content. In your case with minimal modifications you can use the less fancy and efficient method of blocking calls with BufferedReader.ready() to prevent blocking:
String partialLine="";
public static String monitorResponse() throws Exception {
System.out.println("Listening for a response...");
int nextByte;
String nextChar;
while (inputStream.ready()) {
nextByte = inputStream.read();
nextChar = Character.toString ((char) nextByte);
partialLine += nextChar;
if ("\n".equals(nextChar)) {
String line = partialLine;
partialLine = "";
return line.replace("\r\n", "");
}
}
return "";
}
Check out http://tutorials.jenkov.com/java-nio/nio-vs-io.html for more info.
Is there anyway I can add a timeout on the BufferedReader?
No, but you can set a timeout on the Socket, with Socket.setSoTimeout().
I have tried multiple solutions like adding a .setSoTimeout() to the socket before creating the BufferedReader but all that did was close the connection/socket after the specified time.
No it doesn't close the socket. It throws SocketTimeoutException, which you should catch and handle as pertinent. If the socket is being closed, you're closing it. Solution: don't.
Related
I have created this code snippet in both a single threaded version and multithreaded for a client/server setup I have going. I have tested both (recording the avg turn around time) and have gotten EXTREMELY similar results within margin of error when running multiple simple server commands at once. have I implememnted my client handler wrong?
This is my first time trying to implement a multithreaded server and from my understanding it just a matter of putting in a client handler being
`
class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
`
below is the snippet of the whole server code.
`
public class Server {
public static void main(String[] args) {
if (args.length < 1) return;
int port = Integer.parseInt(args[0]);
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Server is listening on port " + port);
while (true) {
Socket socket = serverSocket.accept();
System.out.println("New client connected");
new ServerThread(socket).start();
}
} catch (IOException ex) {
System.out.println("Server exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
try {
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
String text;
do {
text = reader.readLine(); // reads text from client
Process p = Runtime.getRuntime().exec(text);
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
String outputLine;
while ((outputLine = stdout.readLine()) != null) { // while serverMsg is not empty keep printing
writer.println(outputLine);
}
stdout.close();
writer.println("ENDCMD");
// Text here should just write back directly what the server is reading...?
}
while (!text.toLowerCase().equals("exit"));
socket.close();
} catch (IOException ex) {
System.out.println("Server exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
`
I have tested both (recording the avg turn around time) and have gotten EXTREMELY similar results within margin of error when running multiple simple server commands at once. have I implememnted my client handler wrong?
If you are not making a new connection for each command that you send, then this would be expected. Since each connection runs on one thread, a multi-threaded approach, as you have shown, would have the same speed as if you didn't make a new thread for each connection. The difference is that, without multi-threading, you can only have one connection at a time.
I have server and client applications running on my local machine.
Client takes file, changes it and sends to server, then server responds if the file is correct. Client does it multiple times, sending one file at a time.
I send two files from client and on the second file I get Connection reset
Server snippet:
private void initServer() throws IOException {
while (true) {
ServerSocket server = new ServerSocket(55555);
Socket fromclient = server.accept();
InputStream sin = fromclient.getInputStream();
OutputStream sout = fromclient.getOutputStream();
DataInputStream in = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);
String line = in.readUTF();
if (line.equals("new file")) {
long fileSize = in.readLong();
tempSavedFile = new File("/home/evgeniy/Files/Downloads/temp");
tempSavedFile.createNewFile();
try (FileOutputStream fos = new FileOutputStream(tempSavedFile)) {
int t;
for (int i = 0; i < fileSize; i++) {
t = sin.read();
fos.write(t);
}
}
if (checkPadding(tempSavedFile)) {
out.writeInt(PADDING_OK_RESPONSE);
} else {
out.writeInt(PADDING_ERROR_RESPONSE);
}
out.flush();
}
out.close();
in.close();
sout.close();
sin.close();
fromclient.close();
server.close();
}
}
Client class that calls new thread in for loop
for (byte i = 0; i < 2; i++) {
Callable callable = new FileSender(tempFile);
FutureTask<Integer> ftask = new FutureTask<>(callable);
Thread thread = new Thread(ftask);
thread.start();
int response = 3244;
try {
response = ftask.get();
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(FXMLController.class.getName()).log(Level.SEVERE, null, ex);
}
putMessage(String.valueOf(response));
Client Callable thread:
public Integer call() throws Exception {
Socket socket = new Socket(address, serverPort);
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
DataInputStream in = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);
out.writeUTF("new file");
out.flush();
out.writeLong(file.length);
out.flush();
sout.write(file);
sout.flush();
System.out.println(socket.isConnected());
int response = in.readInt();
System.out.println("--------RESP="+response);
out.close();
in.close();
sin.close();
sout.close();
socket.close();
return response;
}
As you can see I send two files, and get this console output on client app:
true
--------RESP=200
true
ноя 20, 2018 5:16:36 PM com.evgeniy_mh.paddingoracle.FXMLController SendFileToServer
SEVERE: null
java.util.concurrent.ExecutionException: java.net.SocketException: Connection reset
Also, I don't understand why socket is ok, but
int response = in.readInt();
raising Connection reset exception.
Your code creates a new ServerSocket and later closes the created server socket for every single request that it processes. The code does not use the same ServerSocket instance to serve multiple requests.
The connection reset failure appears to be because of this, as when the second request is creating a socket connection with the server, the existing ServerSocket is closed and recreated on the same port leading to the connection being reset. For a start try taking out the ServerSocket creation outside the while loop.
private void initServer() {
try (ServerSocket server = new ServerSocket(5555)) {
while (true) {
Socket fromclient = server.accept();
... // remaining code
fromclient.close();
}
} catch (IOException ioe) {
// handle failures
}
}
The try-with-resources handles the .close() call on the AutoCloseable server socket.
Also, note that the requests would be processed serially on a single thread in your code. Usually the Socket obtained for a connection from the ServerSocket#accept() (or the streams derived from it) is passed to a separate thread for processing unlike your code that processes the requests serially.
currently I am trying to send multiple messages from a client to a server and echo them on the server but somehow my message is not arriving at the server until i press CTRL+Z(D) and hit enter.
My loop runs as long as the user does not enter "quit" but altough I write my message to the OutputStream and flush it my message does not show on the Server side as if my Client still reads input.
(I do not want to use BufferedReaders or Threads at the moment it's purely for learning reasons.)
Would be nice if someone could tell me where my mistake/error lies.
Read also the javadocs but still can not find my mistake.
Client.java
public class Client {
//class members
private String msg = null;
private Scanner scn = null;
public Client(String ip, int port) throws IOException {
//Connect to Server
try(Socket socket = new Socket(ip,port))
{
//Initialize class members
scn = new Scanner(System.in); //Init Scanner
msg="";
System.out.println("Enter message:");
//Write to Socket
OutputStream out = socket.getOutputStream();
while(!msg.equals("quit"))
{
msg=scn.nextLine();
out.write(msg.getBytes(), 0, msg.length());
out.flush();
}
}
catch (IOException ex)
{
System.err.println(ex);
}
}
Server.java
public class Server {
//class members
private String msg = null;
public Server(int port) throws IOException {
//Setup ServerSocket.
ServerSocket server = new ServerSocket(port);
System.out.println("SERVER: Launched service.");
//Accept incoming connection requests.
while(true) {
try(Socket connection = server.accept())
{
System.out.println("SERVER: Client connection accepted.");
//Read Input
StringBuilder line = new StringBuilder();
InputStream in = connection.getInputStream();
for(int c=in.read(); c!=-1; c=in.read())
{
line.append((char) c);
}
System.out.println(line);
}
catch (IOException ex)
{
System.out.println("SERVER: Client disconnected!");
}
}
}
sincerely,
rhyleigh
Your server prints nothing until read() returns -1.
read() returns -1 at end of stream.
Over a TCP socket, end of stream is only caused by the peer closing the connection.
Your server's peer, i.e. the client, doesn't close the connection until you type ^Z at the terminal. which causes an unstated exception to be thrown.
Your program is working as designed.
I have read through most similar questions in Stack-overflow . But i can't find similar one.
I build one client and one server. For my client networking, i build a class which contains a socket and many relevant methods like this :
public class Connector {
private Socket socket;
private DataOutputStream output;
private DataInputStream input;
public Connector(int x) throws UnknownHostException, IOException{
socket=new Socket("localhost",x);
}
public boolean isConnected(){
return socket.isConnected();
}
public void sendInfo(String str) throws IOException{
output = new DataOutputStream(socket.getOutputStream());
output.writeUTF(str);
output.flush();
}
public String receiveInfo() throws IOException{
input = new DataInputStream(socket.getInputStream());
return input.readUTF();
}
public boolean loginSuccess() throws IOException{
input = new DataInputStream(socket.getInputStream());
return input.readBoolean();
}
}
and when my client runs(the server run in my IDE),
String userAccount = "VerifyAccount" + "#" + userNametf.getText() + "#" + passwordtf.getText() + "#" + i;
connector.sendInfo(userAccount);
if(connector.isConnected())
System.out.println("the connector is still connected!");
else
System.out.println("the connector is no connected!");
if(connector.loginSuccess()){
System.out.println("Log in success");
}
else;
and this is my server:
ServerSocket serverSocket = new ServerSocket(8000);
while(true){
Socket socket = serverSocket.accept();
Thread thread = new Thread(()->{
try{
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
String tempStr = input.readUTF();
System.out.println("Server receive data : "+tempStr);
String[] tempStrArray = tempStr.split("#");
if(tempStrArray[0].equals("VerifyAccount")){
if(UserVerification.isValid(tempStr.substring(14))==1){
output.writeBoolean(true);
output.flush();
}
else{}
}
else if(tempStrArray[0].equals("RegisterAccount")){}
else{}
}
catch(IOException ex){
ex.printStackTrace();
}
});
thread.start();
}
So the whole process is that the client socket connects to the server socket ,
then client send one string to the server , the server process the string , and write a boolean value back to the client , but when i call connector.LoginSuccess() , the compiler will throw an exception like this:enter image description here
You are never closing the accepted socket. You are also attempting to read a boolean that may never be sent. And, as I said in comments, isConnected() doesn't do what you think it does: it doesn't magically start returning false when the peer disconnects.
I'm trying to get a simple multithreaded proxy to work in Java. However I don't manage to get the webpage show up in my browser, after the first GET request and the response from the webpage, the program is just stuck (as you can see from my code, I'm printing everything i get on the stdout for debugging, and there I see the sourcecode of the webpage, however after printing out "After Client Write", nothing happens (no exception, just nothing...)).
import java.net.*;
import java.util.*;
import java.io.*;
public class Proxy
{
public static void main(String[] args)
{
try
{
ServerSocket listensocket = new ServerSocket(Integer.valueOf(args[0]));
while(true)
{
System.out.println("wait");
Socket acceptsocket = listensocket.accept(); // blocking call until it receives a connection
myThread thr = new myThread(acceptsocket);
thr.start();
}
}
catch(IOException e)
{
System.err.println(">>>>" + e.getMessage() );
e.printStackTrace();
}
}
static class myThread extends Thread
{
Socket acceptsocket;
int host, port;
String url;
myThread(Socket acceptsocket)
{
this.acceptsocket=acceptsocket;
}
public void run() {
try
{
System.out.println("hello");
Socket client = acceptsocket;
//client.setSoTimeout(100);
InputStream clientIn = client.getInputStream();
//BufferedInputStream clientIn=new BufferedInputStream(clientis);
OutputStream clientOut = client.getOutputStream();
System.out.println("hello");
String clientRequest = readStuffFromClient(clientIn); // parses the host and what else you need
System.out.print("Client request: -----\n"+clientRequest);
Socket server;
server = new Socket("xxxxxxxxxxxxx" , 80);
InputStream serverIn = server.getInputStream();
//BufferedInputStream serverIn=new BufferedInputStream(serveris);
OutputStream serverOut = server.getOutputStream();
serverOut.write(clientRequest.getBytes());
serverOut.flush();
String serverResponse = readStuffFromClient(serverIn);
System.out.print("Server Response: -----\n"+serverResponse);
clientOut.write(serverResponse.getBytes());
clientOut.flush();
System.out.println("After Client Write");
clientIn.close();
clientOut.close();
serverIn.close();
serverOut.close();
server.close();
client.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
private String readStuffFromClient(InputStream clientdata)
{
ByteArrayOutputStream response = new ByteArrayOutputStream();
StringBuffer request=new StringBuffer(8192);
int i, httpstart,n=-1 ;
byte[] buffer = new byte[8192];
System.out.println("beforetry");
try
{
while((n = clientdata.read(buffer))!=-1)
{
System.out.println("before");
response.write(buffer,0,n);
//response.flush();
}
request=new StringBuffer(response.toString());
/*System.out.println("new:"+n+" "+ request.toString());
System.out.println("End client data");*/
}
catch (Exception e)
{
System.out.println("here");
System.out.println(e);
e.printStackTrace();
i = -1;
}
System.out.println("End manipulation method");
return request.toString();
}
}
}
(this is a stripped down not working example of my program, from the comments one can see I already tried to use BufferedInputStream). In general, this program is very unresponsive even for the first GET request from the browser. When I only read the clientdata once (not in a loop), I get a little bit further, e.g. get more GET/Response pairs, but at some point the program still gets stuck.
Somehow I think either I've a real trivial error I just don't manage to see, or the program should work, but simply doesn't for no real reason.
Any help is appreciated, thanks in advance!
You need two threads: one to read from the client and write to the server, and one to do the opposite, for each accepted socket. There is a further subtlety: when you read EOS from one direction, shutdown the opposite socket for output, and then if the input socket for that thread is already shutdown for output, close both sockets. In both cases exit the thread that read the EOS.
Try getting first the OutputStream and then the InputStream!
InputStream clientIn = client.getInputStream();
OutputStream clientOut = client.getOutputStream();
change it to:
OutputStream clientOut = client.getOutputStream();
InputStream clientIn = client.getInputStream();
This will make it work:
It will check if there is more data available to read
Still, it's important that you use BufferedIS because I think ByteArrayIS doesn't implement available method.
BufferedInputStream bis = new BufferedInputStream(clientdata);
System.out.println("beforetry");
try {
while(bis.available() > 0){
n = bis.read(buffer);
response.write(buffer, 0, n);
}