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.
Related
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.
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.
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.
I'm trying to program a Server Client program where the CLIENT will be prompt if the SERVER closes or loses connection. What happens is once I connect the server and the client then disconnects the server it doesn't go to the ConnectException part
example: I opened the Server and Client connects, in the Client it will show that "You are connected to the Server", then if the Server disconnects there should be a "Server is disconnected". and when the Server reopens it will prompt the Client that he's connected to the Server
How can I continuously check if the Server is open or disconnected
here's my code:
SERVER
public class Server
{
private static Socket socket;
public static void main(String[] args)
{
try
{
int port = 25000;
ServerSocket serverSocket = new ServerSocket(port);
//Server is running always. This is done using this while(true) loop
while(true)
{
//Reading the message from the client
socket = serverSocket.accept();
System.out.println("Client has connected!");
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String number = br.readLine();
System.out.println("Message received from client is "+number);
//Multiplying the number by 2 and forming the return message
String returnMessage;
try
{
int numberInIntFormat = Integer.parseInt(number);
int returnValue = numberInIntFormat*2;
returnMessage = String.valueOf(returnValue) + "\n";
}
catch(NumberFormatException e)
{
//Input was not a number. Sending proper message back to client.
returnMessage = "Please send a proper number\n";
}
//Sending the response back to the client.
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
System.out.println("Message sent to the client is "+returnMessage);
bw.flush();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
CLIENT
public class Client
{
private static Socket socket;
public static void main(String args[])
{
Scanner input=new Scanner(System.in);
try
{
String host = "localhost";
int port = 25000;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
System.out.println("Connected to the Server");
}
catch (ConnectException exception)
{
System.out.println("Server is still offline");
}
catch(IOException ex)
{
System.out.println("Server got disconnected");
}
}
}
Well, the best way to tell if your connection is interrupted is to try to read/write from the socket. If the operation fails, then you have lost your connection sometime.
So, all you need to do is to try reading at some interval, and if the read fails try reconnecting.
The important events for you will be when a read fails - you lost connection, and when a new socket is connected - you regained connection.
That way you can keep track of up time and down time.
you can do like this
try
{
Socket s = new Socket("address",port);
DataOutputStream os = new DataOutputStream(s.getOutputStream());
DataInputStream is = new DataInputStream(s.getInputStream());
while (true)
{
os.writeBytes("GET /index.html HTTP/1.0\n\n");
is.available();
Thread.sleep(1000);
}
}
catch (IOException e)
{
System.out.println("connection probably lost");
e.printStackTrace();
}
or you can simply et connection time out like this socket.setSoTimeout(timeout); to check connectivity
or you can use
socket.getInputStream().read()
makes the thread wait for input as long as the server is connected and therefore makes your program not do anything - except if you get some input and
returns -1 if the client disconnected
or what you can do is structure your code in this way
while(isConnected())
{
// do stuffs here
}
I have the following Situation.
I have a Server class.
I have a Client class.
I have a MultiServerThread class.
When a Client connects to a Server, the Server creates a new MultiServerThread, which is processing the Input from the Client. That way I can have multiple Clients. So far so good.
The connection goes via TCP.
A short example:
Server class:
...
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(9999);
} catch (IOException e) {
System.err.println("Could not listen on port: " + serverSocket.getLocalPort() + ".");
System.exit(-1);
}
while (listening) {
new MultiServerThread(serverSocket.accept()).start();
}
serverSocket.close();
}
...
Client class:
...
public static void main(String[] args) throws IOException {
socket = new Socket(hostname, port);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer;
String fromUser;
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
if (fromServer.equals("Bye.")) {
break;
}
fromUser = stdIn.readLine();
if (fromUser != null) {
System.out.println("Client: " + fromUser);
out.println(fromUser);
}
}
out.close();
in.close();
stdIn.close();
socket.close();
}
...
MultiServerThread class:
...
public MultiServerThread(Socket socket) throws SocketException {
super("MultiServerThread");
this.socket = socket;
// dSocket = new DatagramSocket(4445);
}
public void run() {
try {
PrintWriter myOutput = new PrintWriter(socket.getOutputStream(), true);
BufferedReader myInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
myOutput.println("Connected to client and ready to accept commands.");
while ((clientInput = myInput.readLine()) != null) {
//A SIMPLE LOGIN A USER
if (clientInput.contains("!login")) {
//save some string given by client into loggedUser
String loggedUser = clientInput.substring(7);
}
myOutput.close();
myInput.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
What I need is:
I need to implement a notification that comes from a Server when for example the Username is "Bob". If the username is "Bob", the server should give a notification to the Client "Bob is here again!". In my project/homework this should be done with datagrams in Java.
So if the clientinput is "!login bob" then a datagram packet with the message ("Bob is here again!") should be sent to the client.
Question: Where exactly should I put the code of the Datagram request in? Can I put the datagram packet request into the MultiServerThread or into the Client?
It would be easier in the MultiServerThread because it already handles the !login.
Here:
if (clientInput.contains("!login")) {
//save some string given by client into loggedUser
String loggedUser = clientInput.substring(7);
//send datagram request to Server???
}
But this is going against the principle of networking?
you need to send the UDP port number to your client through the initial TCP connection. Then you start listening for UDP datagrams on your client on that port number. All other communications from server -> client will be on this udp socket. This is what your assignment suggests
I got it working ;-)
I definied a udp port in the thread and client class...
the client class got his port with arguments... it gave the udp Port to the thread... so both had the udp ports ;)