Server terminate from infinite while loop? - java

I'm totally new in java.
I started to learn java network programming.
My problem: i put my server in infinite while loop to keep working.
I send a message to the server, when the server reads this message it should perform some action. it is performed successfully but after exiting my client program, the server also terminates although i put it in infinite while loop.
my client code:
private void check_ordersActionPerformed(java.awt.event.ActionEvent evt) {
try {
Socket ss = new Socket("localhost", 4000);
PrintStream pr = new PrintStream(ss.getOutputStream());
pr.println("Supplier Orders");
pr.println(Supplier.username);
pr.close();
this.dispose();
} catch (IOException ex) {
Logger.getLogger(supp_page.class.getName()).log(Level.SEVERE, null, ex);
}
my server code:
int iiiiii = 0;
ServerSocket s1 = new ServerSocket(4000);
String request = null;
while(iiiiii == 0)
{
Socket ss = s1.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(ss.getInputStream()));
request = in.readLine();
switch (request) {
case "Supplier Orders":
Supplier.username = in.readLine();
orders rs = new orders();
rs.setLocation(350, 250);
rs.setSize(800, 350);
rs.setVisible(true);
rs.setTitle("Orders Table");
rs.setResizable(false);
break;
// some other messages here but iam focus on above one
}
}
let me explain more: when i call this method it send a message to the client "Supplier Orders" and a username .... when server receives this message it should launch a gui page that contains some data of the that supplier i gave username to the server.
but when i close client the server also terminates ... that should not be happened. i want the server to keep working and not exit.
so how to fix this ? .. sorry for long post.
Edit
The code for gui page, it should show some data on table: it showed data successfully but as i mention when i close client, the server also closed which i don't want to happen, i want server to keep working not to close
public class orders extends javax.swing.JFrame {
DefaultTableModel t = new DefaultTableModel();
public orders() throws IOException, ClassNotFoundException {
initComponents();
request.setModel(t);
t.addColumn("ID");
t.addColumn("PRODUCT Name");
t.addColumn("PRODUCT TYPE");
t.addColumn("PRODUCT QUANTITY");
t.addColumn("SUPPLIER ID");
t.addColumn("SUPPLIER NAME");
t.addColumn("SUPPLIER COMPANY");
t.addColumn("SUPPLIER ADDRESS");
t.addColumn("SUPPLIER PHONE NUMBER");
ObjectInputStream oin = new ObjectInputStream(new FileInputStream("Orders.bin"));
ArrayList<Order> a = (ArrayList)oin.readObject();
Iterator<Order> iter = a.iterator();
oin.close();
while(iter.hasNext())
{
Order r = iter.next();
if(Supplier.username.equals(r.getP().getS().getId() + r.getP().getS().getCompany()) && r.getStatus().equals("PENDING"))
{
t.addRow(new Object[]{r.getP().getId(),r.getP().getName(),r.getP().getType(),r.getP().getQuantity(),r.getP().getS().getId()
,r.getP().getS().getName(), r.getP().getS().getCompany(), r.getP().getS().getAddress(), r.getP().getS().getPhone_no()});
}
}
}
}

The issue is that your client is closing the socket between the client and server when the client exits as DBug said. Since you're blocking on the in.readline() in the server an IOException (Socket Closed Exception) is thrown. Your code is not handling that IOException and your while loop won't be enough to prevent the server code from exiting. You need to add a few try/catches to catch these exceptions.
Consider adding a few finally blocks to ensure your sockets and streams get closed properly.

Related

Java Client Server Program Takes input infinitely

I'm new to java socket programming, I'm making a client server program. the server is multithreaded.
when the client connection with server is open. the server sends a text block to the client like this:
connection is open with the server....
Welcome Please Chose one of the following Operations
Insert, Read, Update, Delete
Type Exit to terminate connection.
when I type read or exit or any of the operations it works fine and the server responds.
but the problem happens when I chose an operation i.e insert --> when the server responds and asks me for input and I wanna insert a value, the program keeps taking input infinitely for endless lines I don't know where the problem and how it happens.
it's the same code, the client sends the input as one line when choosing operation but when I chose insert operation and the server is expecting a value it takes it as infinite endless lines.
Client class
public class Client1 {
public static void main(String[] args) throws IOException {
Socket socket=null;
try {
System.out.println("sending connection request to host 127.0.0.1 at port 2000");
socket = new Socket("127.0.0.1", 2000);
System.out.println("connection is open with the server....");
Scanner scn = new Scanner(System.in);
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
DataInputStream dis = new DataInputStream(socket.getInputStream());
while (true) {
System.out.println(dis.readUTF());
String tosend = scn.nextLine();
dos.writeUTF(tosend);
// If client sends exit,close this connection
// and then break from the while loop
if (tosend.equals("Exit")) {
System.out.println("Closing this connection : " + socket);
socket.close();
System.out.println("Connection closed");
break;
}
String received = dis.readUTF();
System.out.println(received);
}
// closing resources
scn.close();
dis.close();
dos.close();
}
catch (Exception e ){
System.out.println(e);
} finally {
try {
if (socket != null) socket.close();
} catch (Exception e){
System.out.println(e);
}
}
}
Server Class
public class ServerThread extends Thread{
Socket socket ;
DataInputStream dis;
DataOutputStream dos;
ServerThread(Socket socket,DataInputStream dis,DataOutputStream dos ){
this.socket = socket;
this.dis=dis;
this.dos=dos;
}
#Override
public void run(){
String received;
String toreturn;
String welcomeText = """
Welcome Please Chose one of the following Operations
Insert, Read, Update, Delete
Type Exit to terminate connection.""";
while (true){
try {
// Ask user what he wants
dos.writeUTF(welcomeText);
// receive the answer from client
received = dis.readUTF();
if(received.equals("Exit"))
{
System.out.println("Client " + this.socket + " sends exit...");
System.out.println("Closing this connection.");
this.socket.close();
System.out.println("Connection closed");
break;
}
// write on output stream based on the
// answer from the client
switch (received) {
// the problem starts here if I chose insert and wanna print what the user typed, it takes
//input infinitely from the user
case "Insert":
toreturn = "Inserting new info...";
dos.writeUTF(toreturn);
String out = dis.readUTF();
dos.writeUTF("Accepted");
dos.writeUTF(out);
break;
case "Read":
toreturn = "Reading User Info...";
dos.writeUTF(toreturn);
break;
case "Update":
toreturn = "Updating User Info...";
dos.writeUTF(toreturn);
break;
case "Delete":
toreturn = "Deleting User Info";
dos.writeUTF(toreturn);
break;
default:
dos.writeUTF("Unknown User");
break;
}
} catch ( IOException e) {
e.printStackTrace();
}
}
try
{
// closing resources
this.dis.close();
this.dos.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
I don't know how this loop happens especially since the server accepts input correctly when choosing operations but when insert operation is chosen it just takes input infinitely, can anyone help please, i cant implement any operation if this problem persists.
I think its your Client, in the while loop try to remove the second read from server, it's because you once read all what server sents, and when the loop starts again wants to read from server but there is nothing to read and becomes idle.

Trying to Get a new ServerSocket to open fails

I was given the below code by my teacher for a class. I ran it one or twice and it worked fine. However I suddenly cannot get it to run from the command prompt on Windows 8 anymore. No matter what port I specify it just prints "Opening port..." and never continues. No exception is ever thrown. I have disabled my firewall and antivirus and it does not seem to work. I have added a print statement as the first line of the try catch block and it will print but it just will not create the new Socket. I am sure it is something in my Windows settings but I am unsure as to what or how to resolve it.
// Server program
// File name: "TCPServer.java"
import java.io.*;
import java.net.*;
public class TCPServer
{
private static ServerSocket servSock;
public static void main(String[] args)
{
System.out.println("Opening port...\n");
try{
// Create a server object
servSock = new ServerSocket(Integer.parseInt(args[0]));
}
catch(IOException e){
System.out.println("Unable to attach to port!");
System.exit(1);
}
do
{
run();
}while (true);
}
private static void run()
{
Socket link = null;
try{
// Put the server into a waiting state
link = servSock.accept();
// Set up input and output streams for socket
BufferedReader in = new BufferedReader(new InputStreamReader(link.getInputStream()));
PrintWriter out = new PrintWriter(link.getOutputStream(),true);
// print local host name
String host = InetAddress.getLocalHost().getHostName();
System.out.println("Client has estabished a connection to " + host);
// Receive and process the incoming data
int numMessages = 0;
String message = in.readLine();
while (!message.equals("DONE"))
{
System.out.println(message);
numMessages ++;
message = in.readLine();
}
// Send a report back and close the connection
out.println("Server received " + numMessages + " messages");
}
catch(IOException e){
e.printStackTrace();
}
finally{
try{
System.out.println("!!!!! Closing connection... !!!!!\n" + "!!! Waiting for the next connection... !!!");
link.close();
}
catch(IOException e){
System.out.println("Unable to disconnect!");
System.exit(1);
}
}
}
}
This code works fine. The problem is the code for the client. The answer to your problem is already written in a comment in your code.
// Put the server into a waiting state
link = servSock.accept();
The server goes into a waiting state until it gets a connection. The client is the one that would be getting the error since it did not connect. If the client was working correctly the code would continue and you would get the additional output.

SocketTimeoutException in client readLine() method on AWS

UPDATE:
I noticed that it works fine on a Windows machine, but it fails on Mac.
I created a basic Java Server code for socket connection. It runs on AWS Linux AMI, and I make a client connection from my computer. It works fine for first 4-5 answers from the client. However, after 4th or 5th answer, I don't get any response from the server and it just hangs. After a while, it gives SocketTimeout Exception.
I set socket timeout with setSoTimeout() in both side, and it didn't change anything. I wonder if it has anything to do with Amazon.
Client Code:
public static void main(String[] args) {
final int portNumber = 9090;
String connected = "1";
System.out.println(WELCOME);
try {
Socket socket = new Socket("ip", portNumber);
socket.setSoTimeout(0);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
out.println(connected);
while (connected.equals("1")) {
//read in situation
String situation = readInSituation(socket, input).replace(DELIMETER, "\n");
System.out.println(situation);
//send option
Scanner in = new Scanner(System.in);
System.out.print("Enter option: ");
out.println(in.nextLine());
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static String readInSituation(Socket socket, BufferedReader input) throws Exception {
while (!input.ready()) {
Thread.sleep(200);
}
return input.readLine();
}
Server Code is more complicated, but all it does is to respond to commands and print basic text on the screen.
Thanks
Don't use PrintWriter over the network, as it swallows exceptions, most probably a prior 'connection reset'. Use BufferedWriter. NB The ready() loop is literally a waste of time.

Socket programming. Program creating 2 connections instead of just 1

I am building a client/server application, for some socket programming exercise.
Below is construction + run method of my server class. The server awaits a respond from the client, which in this case is just a string.
The problem is that it seems to make two connections when the client respond. From my print statements i can see that all the code in the run method is run twice, and then the first line once again.
Why would dateServer.accept(); accept a connection for only one client request?
public Server() throws Exception {
dateServer = new ServerSocket(3001);
System.out.println("Server lytter på port 3000.");
this.start();
}
public void run() {
while (true) {
try {
System.out.println("waiting for client to request");
Socket client = dateServer.accept();
System.out.println("connection established");
Connect c = new Connect(client);
clients.add(c);
this.sleep(5000);
} catch (Exception e) {
}
}
}
--EDIT--
Client code that talks to server (Message is a simple "wrapper" class"):
System.out.println("Write to server:");
String name = scanner.nextLine();
Message message = new Message(name, null);
oos.writeObject(message);
oos.flush();
If all the prints happen twice there must have been two connections. The first line prints again after that because you're in a loop.
NB:
Never ignore exceptions: especially IOExceptions.
The sleep is completely pointless. accept() will block while there are no incoming connections. You are literally wasting time here.

Simple Socket Programming and thread with JDBC arraylist

I'm already taking some questions from database with JDBC, resultsets, etc... then putting this into arraylists.. and show all via Java GUI.
However now i want to extend this using sockets, threads etc.. to learn this staff.
This time i want to use three tier architecture approach, where the database access is
sorted in the application layer which interacts the same old database.
Application layer is going to act like a server which accept incoming
requests of multiple clients and provide the interaction with the data level.
I try something like this;
Server side: taking questions(20 tf questions, 8 multiple), writing to arraylist and sends to the client.
I send only tf questions. How can i send also multiples ?
Is this true way to do this ?
If threads are necessary ? How can i implement threads to this ?
public class trainingServer {
static ArrayList<TrueFalse> truefalseList = new ArrayList<TrueFalse>();
static ArrayList<Multiple> multipleList = new ArrayList<Multiple>();
static ArrayList<String> clientAnswers = new ArrayList<String>();
public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException {
Connection con;
Statement st;
ResultSet resultSet, resultSet2;
ServerSocket serverSocket = null;
Socket clientSocket = null;
ObjectOutputStream out = null;
ObjectInputStream in = null;
PrintWriter outScore = null;
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost/db", "root", "");
st = con.createStatement();
try {
serverSocket = new ServerSocket(9999); //listening on port 9999
} catch (Exception e) {
System.out.println("Port Error!");
}
System.out.println("Server is ready for connection..");
clientSocket = serverSocket.accept();
out = new ObjectOutputStream(clientSocket.getOutputStream());
in = new ObjectInputStream(clientSocket.getInputStream());
outScore = new PrintWriter(clientSocket.getOutputStream(), true);
resultSet = st.executeQuery("SELECT No, Question, Answer FROM truefalse");
//adding true/false questions and their answers to tfList from database
while (resultSet.next())
{
TrueFalse qa = new TrueFalse();
qa.number=resultSet.getInt(1);
qa.question=resultSet.getString(2);
qa.answer=resultSet.getString(3);
truefalseList.add(qa);
}
//writing true-false part to object output stream to send client
// for(TrueFalse tf : truefalseList)
// out.writeObject(tf);
resultSet2 = st.executeQuery("SELECT No, Question, Ans1, Ans2, Ans3, Ans4, Ans5, Explanation, Trueans FROM multiple");
//adding multiple questions and their answers to multList from database
while (resultSet2.next())
{
Multiple qm = new Multiple();
qm.num=resultSet2.getInt(1);
qm.question=resultSet2.getString(2);
qm.answer1=resultSet2.getString(3);
qm.answer2=resultSet2.getString(4);
qm.answer3=resultSet2.getString(5);
qm.answer4=resultSet2.getString(6);
qm.answer5=resultSet2.getString(7);
qm.explanation=resultSet2.getString(8);
qm.trueAns=resultSet2.getString(9);
multipleList.add(qm);
}
//writing mult. part to object output stream to send client
// for(Multiple mult : multipleList)
// out.writeObject(mult);
out.writeUTF("Server ready");
out.flush();
// If we are here, then connection was probably not a portscan
out.writeObject(truefalseList);
out.writeObject(multipleList);
out.flush();
clientAnswers = (ArrayList<String>) in.readObject();
// score = (Score)in.readObject();
// do something with score.
outScore.println(checkAnswers());
outScore.flush();
out.close();
in.close();
outScore.close();
clientSocket.close();
serverSocket.close();
}
static int checkAnswers(){
int score=0;
for(int i=0 ; i<clientAnswers.size() ; i++)
{
if(i<20)
{
if(clientAnswers.get(i).equalsIgnoreCase(truefalseList.get(i).answer))
{
score=score+3;
}
}
else
{
int count=0;
if(clientAnswers.get(i).equalsIgnoreCase(multipleList.get(count).trueAns))
{
score=score+5;
count++;
}
}
}
return score;
}
}
Client side: (except gui staff etc..)
Socket soket = null;
ObjectInputStream in = null;
ObjectOutputStream out = null;
BufferedReader inScore = null;
try {
soket = new Socket("localhost",9999);
in = new ObjectInputStream(soket.getInputStream());
out = new ObjectOutputStream(soket.getOutputStream());
inScore = new BufferedReader(new InputStreamReader(soket.getInputStream()));
String serverReady = in.readUTF();
tfList = (ArrayList<TrueFalse>) in.readObject();
multList = (ArrayList<Multiple>) in.readObject();
// score = new Score();
// prepare the score object
out.writeObject(userAnswers);
out.flush();
// wait for server to process score
returned_score = inScore.read();
System.out.println(returned_score);
// server has processed score and send "Bye".
} catch (ConnectException ce) {
System.out.println("Cannot connect to the server!");
} catch (IOException ie) {
System.out.println("I/O Error!");
}
in.close();
out.close();
inScore.close();
soket.close();
The true way of doing this depends on your non-functional requirements. If you expect non-Java clients to request the (status) data from the database, or clients are behind a proxy, then write your application server as a web-service.
Since you are writing a server that clients will depend on, also think about scalability (deploy the web-service on multiple web-servers behind a load-balancer) and availability (if one web-server goes down, the load-balancer should direct requests to other web-servers that are still up). And don't forget maintainability: ideally you should be able to upgrade/downgrade your application server without clients noticing.
If there are only Java clients (or the data on the line is only question-answer type text like with telnet), then you will need threads and also a database connection pool. I have used Yapool to create an "always on" application server like this. It contains a ServerSocket that you can use/look at to learn this stuff (see also the unit tests). A database pool implementation is also included.
I have also combined Yapool with a basic JSP web-service framework to create a war-file that can be deployed on Tomcat, exposing the application server as a (very simple) web-service. The advantage of a web-service like this is that you do not need to worry (much) about threads and connections: Tomcat does that for you. If you want to take it a step further, I suggest learning about REST.
As for receiving two types of lists: you are inventing your own protocol here and are free to send and receive data to/from the client as long as the client mirrors the server protocol exactly. You can send/receive any kind of object with the ObjectInputStream/ObjectOutputStream as long as it is serializable. Lists and Maps are already serializable.
For example server protocol:
out.writeUTF("Server ready");
out.flush();
// If we are here, then connection was probably not a portscan
out.writeObject(tfList);
out.writeObject(multipleList);
out.flush();
clientAnswers = (List<String>) in.readObject();
out.writeInt(checkAnswers());
out.writeUTF("Bye");
out.flush();
With the following client protocol:
String serverReady = in.readUTF();
tfList = (List<TrueFalse>) in.readObject();
multipleList = (List<Multiple>) in.readObject();
out.writeObject(userAnswers);
out.flush();
// wait for server to check answers and return score
int returned_score = in.readInt();
String serverBye = in.readUTF();
// server has processed score and send "Bye".

Categories

Resources