user4359659
user4359659

Reputation: 159

Client-server application in Java

I have a server application in Java, that holds a list of Student objects (implementing Serializable). The client application sends a message with an integer - index of Student object to fetch. Then the selected Student is sent to the client, the client modifies its value and sends back. The application however freezes at some point, and it's probably a problem with the lines I emphasized in the code below.

Server:

public class Server {

    public static void main(String[] arg) {
        ArrayList <Student> studentList = new ArrayList <Student> ();
        studentList.add(new Student(170435, "justyna", "kaluzka", new ArrayList <Float>()));
        studentList.add(new Student(170438, "michal", "szydlowski", new ArrayList <Float>()));
        studentList.add(new Student(170436, "marek", "polewczyk", new ArrayList <Float>()));
        studentList.add(new Student(170439, "jakub", "szydlowski", new ArrayList <Float>()));
        studentList.add(new Student(170430, "anna", "majchrzak", new ArrayList <Float>()));
        studentList.add(new Student(170425, "krzysztof", "krawczyk", new ArrayList <Float>()));
        studentList.add(new Student(170445, "adam", "szydlowski", new ArrayList <Float>()));
        studentList.add(new Student(170415, "karol", "chodkiewicz", new ArrayList <Float>()));
        studentList.add(new Student(170465, "artur", "schopenhauer", new ArrayList <Float>()));

        ServerSocket socketConnection = null;
        ObjectInputStream serverInputStream = null;
        ObjectOutputStream serverOutputStream = null;

        try {
            socketConnection = new ServerSocket(11111);
            System.out.println("Server Waiting");

            Socket pipe = socketConnection.accept();

            serverOutputStream = new ObjectOutputStream( pipe.getOutputStream());
            serverInputStream = new ObjectInputStream( pipe.getInputStream());

            int index = serverInputStream.readInt();
            System.out.println(index);

            //  HERE'S WHEN THE PROBLEM STARTS
            serverOutputStream.writeObject(studentList.get(index));
            Student student = (Student) serverInputStream.readObject();

            System.out.println(student.toString());
        } catch (IOException e) {
            System.out.println(e);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                serverInputStream.close();
                serverOutputStream.close();
                socketConnection.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

Client:

public class Client {

public static void main(String[] arg) {
        Student student = null;
        Socket socketConnection = null;
        ObjectOutputStream clientOutputStream = null;
        ObjectInputStream clientInputStream = null;

        try {
            socketConnection = new Socket("127.0.0.1", 11111);

            clientOutputStream = new ObjectOutputStream(socketConnection.getOutputStream());
            clientInputStream = new ObjectInputStream(socketConnection.getInputStream());

            clientOutputStream.writeInt(0);
            student = (Student) clientInputStream.readObject();

            student.setFamilyName("Konopnicka");

            clientOutputStream.writeObject(student);    
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            try {
                clientOutputStream.close();
                clientInputStream.close();
                socketConnection.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

My knowledge of client-server sockets is vague, so it's most likely a simple mistake. Any ideas?

EDIT: Student class

public class Student implements Serializable {
    private static final long serialVersionUID = -5169551431906499332L;
    private int indexNumber;
    private String name;
    private String familyName;
    private ArrayList<Float> marks;
    private float average;

    public Student(int indexNumber, String name, String familyName,
            ArrayList<Float> marks) {
        this.indexNumber = indexNumber;
        this.name = name;
        this.familyName = familyName;
        this.marks = marks;
        this.average = 0;
        generateMarks();
        calculateAverage();
    }

    public int getIndexNumber() {
        return indexNumber;
    }

    public void setIndexNumber(int indexNumber) {
        this.indexNumber = indexNumber;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getFamilyName() {
        return familyName;
    }

    public void setFamilyName(String familyName) {
        this.familyName = familyName;
    }

    public float getAverage() {
        return average;
    }

    public void setAverage(float average) {
        this.average = average;
    }

    /**
     * Calculates average of all Student's marks.
     */
    public void calculateAverage() {
        float sum = 0;
        for (int i = 0; i < marks.size(); i++) {
            sum += marks.get(i);
        }
        this.average = sum / marks.size();
    }

    /**
     * Generates a random set of marks for the student.
     */
    public void generateMarks() {

        for (int i = 0; i < 10; i++) {
            addMark(new Random().nextFloat() * 5);
        }

    }

    /**
     * Mark getter
     * 
     * @return String representation of marks
     */
    public String getMarks() {
        String marksstr = "";
        for (int i = 0; i < marks.size(); i++) {
            marksstr += marks.get(i).toString() + "   ";
        }
        return marksstr;
    }

    /**
     * Adds a mark to the list.
     * 
     * @param mark
     */
    public void addMark(float mark) {
        marks.add(mark);
    }

    @Override
    public String toString() {
        return "Index number:" + indexNumber + "\tName:" + name
                + "\tFamily name:" + familyName + "\t\tAverage:" + getAverage()
                + "\n";
    }
}

Upvotes: 0

Views: 1100

Answers (1)

Vince
Vince

Reputation: 15146

Initialize your ObjectOutputStream before your ObjectInputSteam on your server.

When you initialize an ObjectInputStream, it waits for "header" data. Your server is waiting for that header data. You need to initialize your ObjectOutputStream first (which sends the header data), THEN your ObjectInputStream.

You can find more about this in here


You must flush your ObjectOutputStream after writing the int. When you write data to a stream, it gets written into a buffer. Data from that buffer is only sent when the stream's buffer is full. An int does not fill it, so you must flush() it to manually send the data from the buffer.

Upvotes: 5

Related Questions