Чистый код. Создание, анализ и рефакторинг — страница 67 из 94

Однопоточная реализация архитектуры  «клиент/сервер»

Листинг А.3. Server.java

package com.objectmentor.clientserver.nonthreaded;


import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

import java.net.SocketException;


import common.MessageUtils;


public class Server implements Runnable {

    ServerSocket serverSocket;

    volatile boolean keepProcessing = true;


    public Server(int port, int millisecondsTimeout) throws IOException {

        serverSocket = new ServerSocket(port);

        serverSocket.setSoTimeout(millisecondsTimeout);

    }


    public void run() {

        System.out.printf("Server Starting\n");


        while (keepProcessing) {

            try {

                System.out.printf("accepting client\n");

                Socket socket = serverSocket.accept();

                System.out.printf("got client\n");

                process(socket);

            } catch (Exception e) {

                handle(e);

            }

        }

    }


Листинг А.3 (продолжение)

    private void handle(Exception e) {

        if (!(e instanceof SocketException)) {

            e.printStackTrace();

        }

    }


    public void stopProcessing() {

        keepProcessing = false;

        closeIgnoringException(serverSocket);

    }


    void process(Socket socket) {

        if (socket == null)

            return;


        try {

            System.out.printf("Server: getting message\n");

            String message = MessageUtils.getMessage(socket);

            System.out.printf("Server: got message: %s\n", message);

            Thread.sleep(1000);

            System.out.printf("Server: sending reply: %s\n", message);

            MessageUtils.sendMessage(socket, "Processed: " + message);

            System.out.printf("Server: sent\n");

            closeIgnoringException(socket);

        } catch (Exception e) {

            e.printStackTrace();

        }


    }


    private void closeIgnoringException(Socket socket) {

        if (socket != null)

            try {

                socket.close();

            } catch (IOException ignore) {

            }

    }


    private void closeIgnoringException(ServerSocket serverSocket) {

        if (serverSocket != null)

            try {

                serverSocket.close();

            } catch (IOException ignore) {

            }

    }

}



Листинг А.4. ClientTest.java

package com.objectmentor.clientserver.nonthreaded;


import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

import java.net.SocketException;


import common.MessageUtils;


public class Server implements Runnable {

    ServerSocket serverSocket;

    volatile boolean keepProcessing = true;


    public Server(int port, int millisecondsTimeout) throws IOException {

        serverSocket = new ServerSocket(port);

        serverSocket.setSoTimeout(millisecondsTimeout);

    }


    public void run() {

        System.out.printf("Server Starting\n");


        while (keepProcessing) {

            try {

                System.out.printf("accepting client\n");

                Socket socket = serverSocket.accept();

                System.out.printf("got client\n");

                process(socket);

            } catch (Exception e) {

                handle(e);

            }

        }

    }


    private void handle(Exception e) {

        if (!(e instanceof SocketException)) {

            e.printStackTrace();

        }

    }


    public void stopProcessing() {

        keepProcessing = false;

        closeIgnoringException(serverSocket);

    }


    void process(Socket socket) {

        if (socket == null)

            return;



Листинг А.4 (продолжение)

        try {

            System.out.printf("Server: getting message\n");

            String message = MessageUtils.getMessage(socket);

            System.out.printf("Server: got message: %s\n", message);

            Thread.sleep(1000);

            System.out.printf("Server: sending reply: %s\n", message);

            MessageUtils.sendMessage(socket, "Processed: " + message);

            System.out.printf("Server: sent\n");

            closeIgnoringException(socket);

        } catch (Exception e) {

            e.printStackTrace();

        }


    }


    private void closeIgnoringException(Socket socket) {

        if (socket != null)

            try {

                socket.close();

            } catch (IOException ignore) {

            }

    }


    private void closeIgnoringException(ServerSocket serverSocket) {

        if (serverSocket != null)

            try {

                serverSocket.close();

            } catch (IOException ignore) {

            }

    }

}


Листинг А.5. MessageUtils.java

package common;


import java.io.IOException;

import java.io.InputStream;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.OutputStream;

import java.net.Socket;


public class MessageUtils {

    public static void sendMessage(Socket socket, String message)

            throws IOException {

        OutputStream stream = socket.getOutputStream();

        ObjectOutputStream oos = new ObjectOutputStream(stream);

        oos.writeUTF(message);

        oos.flush();

    }

    public static String getMessage(Socket socket) throws IOException {

        InputStream stream = socket.getInputStream();

        ObjectInputStream ois = new ObjectInputStream(stream);

        return ois.readUTF();

    }

}

Архитектура «клиент/сервер»  с использованием потоков

Перевод сервера на многопоточную архитектуру сводится к простому изменению функции process (новые строки выделены жирным шрифтом):


void process(final Socket socket) {

    if (socket == null)

        return;


    Runnable clientHandler = new Runnable() {

        public void run() {

            try {

                System.out.printf("Server: getting message\n");

                String message = MessageUtils.getMessage(socket);

                System.out.printf("Server: got message: %s\n", message);

                Thread.sleep(1000);

                System.out.printf("Server: sending reply: %s\n", message);

                MessageUtils.sendMessage(socket, "Processed: " + message);

                System.out.printf("Server: sent\n");

                closeIgnoringException(socket);

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    };


    Thread clientConnection = new Thread(clientHandler);

    clientConnection.start();

}

Приложение Б. org.jfree.date.SerialDate