[Java][Socket] Javaでwebサービス - Socket通信

Java以外のプログラムと通信する場合,Socket通信なるものを使います.


今回はJavaに閉じたお話で,Socket通信について.


Socket通信についてはググったらいろいろ出てきます.google is your friend です.


個人的に,JavaでのSocket通信で大事かなと思った点を書きます.

  • サーバー側がポートを開いてクライアントはサーバーのホスト名とポート番号を指定してつなぎにいく.

ソケット通信の流れは以下になります.
1.サーバーがソケットを作成

ServerSocket serverSocket = new ServerSocket(portNumber);

2.サーバーのソケットを受け入れ体制に

Socket socketOfServer = serverSocket.accept();

3.クライアントがソケットを作成

Socket socketOfClient = new Socket(hostName,portNumber);

4クライアントのソケットをサーバーのソケットとつなげる.(通信開始)

socketOfClient.connect();

5.クライアントからデータを送る
5.1.データをストリームに書き込む

ObjectOutputStream clientOutputStream = new ObjectOutputStream(socketOfClient.getOutputStream());
clientOutputStream.writeObject(data);

5.2.書き込み終了

clientOutputStream.flush();

5.3.サーバーでデータを受け取る

ObjectInputStream serverInputStream =  new ObjectInputStream(socketOfServer.getInputStream());
Object data = serverInputStream.readObject();

6.サーバーからデータを送る
6.1.ストリームに書き込み

ObjectOutputStream serverOutputStream = new ObjectOutputStream(socketOfServer.getOutputStream());
serverOutputStream.writeObject(data);

6.2.書き込み終了

serverOutputStream.flush();

6.3.クライアントでデータを受け取る

ObjectInputStream clientInputStream =  new ObjectInputStream(socketOfServer.getInputStream());
Object data = clientInputStream.readObject();

7クライアントでソケットを閉じる

clientSocket.close();
  • クライアントでソケットを閉じるともう一度サーバー側もソケットを作り直さなければならない.(自動的にsocket.close()がよばれる?)
  • 同じサーバーソケットに同時に複数のソケットをつなげることができる.
  • serverSocket.accept();でそのスレッドはstopする.

clientからconnectされれば動き出す.

  • clientSocket.connect();でそのスレッドはstopする.

serverSocketと繋がれば動き出す.

  • つまり,順番的にaccept()とconnect()どちらを先に実行しても大丈夫.

以下サンプルコード
ソケットの部分をサーバーとクライアントで別々にラップしてます.
クライアントを別スレッドで立ててクライアントから投げた値を素因数分解して,その値を返すプログラムです.

Main.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Main {

    public static void main(String[] args) {
        int portNumber = 50000;
        String hostName = "localhost";
        SocketServer server = new SocketServer(portNumber);
        ClientThread clientThread = new ClientThread(hostName, portNumber);
        Thread thread = new Thread(clientThread);
        thread.start();
        while(true){
            server.Accept();
            ObjectInputStream serverInputStream = server.getObjectInputStream();
            Integer data;
            try {
                data = (Integer)serverInputStream.readObject();
                ArrayList<Integer> array = new ArrayList<Integer>();
                int factor = 2;
                while(data != 1){
                    if( data%factor == 0 ){
                        array.add(factor);
                        data = data/factor;
                    }else{
                        factor++;
                    }
                }
                ObjectOutputStream serverOutputStream = server.getObjectOutputStream();
                serverOutputStream.writeObject(array);
                serverOutputStream.flush();
            } catch (IOException e1) {
                e1.printStackTrace();
            } catch (ClassNotFoundException e1) {
                e1.printStackTrace();
            }
        }
    }
}

SocketClient.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class SocketClient {
    private String hostName;
    private int portNumber;
    private Socket socket;

    public SocketClient(String hostName,int portNumber){
        this.hostName = hostName;
        this.portNumber = portNumber;
    }

    public Socket connect(){
        try {
            this.socket = new Socket(this.hostName,this.portNumber);
        } catch (UnknownHostException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return this.socket;
    }

    public void close(){
        try {
            this.socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public ObjectInputStream getObjectInputStream(){
        try {
            return new ObjectInputStream(this.socket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    public ObjectOutputStream getObjectOutputStream(){
        try {
            return new ObjectOutputStream(this.socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void finalize(){
        try {
            this.socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

SocketServer.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketServer {
    private int portNumber;
    private ServerSocket serverSocket;
    private Socket socket;

    public SocketServer(int portNumber){
        this.portNumber = portNumber;
        try {
            this.serverSocket = new ServerSocket(this.portNumber);
        } catch (IOException e) {
            System.out.println("Failed to Create ServerSocket..");
            e.printStackTrace();
        }
    }

    public void Accept(){
        try {
            this.socket = this.serverSocket.accept();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public ObjectInputStream getObjectInputStream(){
        try {
            return new ObjectInputStream(this.socket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    public ObjectOutputStream getObjectOutputStream(){
        try {
            return new ObjectOutputStream(this.socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    public ServerSocket getServerSocket(){
        return serverSocket;
    }

    public void finalize(){
    }
}

ClientThread.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ClientThread implements Runnable{
    private String hostName;
    private int portNumber;

    public ClientThread(String hostName,int portNumber){
        this.hostName = hostName;
        this.portNumber = portNumber;
    }
    @Override
    public void run() {
        for(int i=2;i<10;i++){
            SocketClient client = new SocketClient(this.hostName, this.portNumber);
            client.connect();
            ObjectOutputStream clientOutputStream = client.getObjectOutputStream();
            Integer data = new Integer(i);
            try {
                System.out.println("Input : "+ data);
                clientOutputStream.writeObject(data);
                clientOutputStream.flush();

                ObjectInputStream clientInputStream = client.getObjectInputStream();
                ArrayList<Integer> getData = (ArrayList<Integer>)clientInputStream.readObject();
                String out = new String();
                for(int j=0;j<getData.size();j++){
                    out += " " + getData.get(j);
                }
                System.out.println("Get :" + out);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            client.close();
        }
    }
}