0
0

More than 3 years have passed since last update.

JAVAでのUDP通信(オンラインチャット実装)

Last updated at Posted at 2021-09-01

目標

顧客があるサービスのオンラインヘルプに問い合わせすると想定し、チャット機能をjavaで実装する。
機能だけ実装し、UI部分は無し。

TODO整理

目標を実現するのに必要なのは以下が考えられます。

  • UDP通信

UDP通信特徴
①リアリティ性が求められない
②かつクライアントとサーバーか、クライアントとクライアントとの通信にこだわらない

今回の実装にUDP通信を使います。

  • スレッド

メッセージ受け取るにも送るのにも同時に行う必要があるのため、スレッドを実装すると考えらる。

実装

  • メッセージ送信処理

UDP通信はクラスDatagramSocketを使う

SendThread.java
package com.maekawa.onlineChat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.nio.charset.StandardCharsets;

public class SendThread implements Runnable {
    //UDP通信を行うためのソケット
    DatagramSocket socket = null;
    //入力を一行ずつ読み込む
    BufferedReader reader = null;
    private int fromPort;
    private String toIp;
    private int toPort;

    //コネクションを一回接続のため、初期化してコンストラクタにした。
    //送信元のポートと送信先IPとポート初期化処理する
    public SendThread(int fromPort, String toIp, int toPort) {
        this.fromPort = fromPort;
        this.toIp = toIp;
        this.toPort = toPort;

        try {
            socket = new DatagramSocket(fromPort);
            //コンソールからの入力ストリームを受ける
            InputStreamReader streamReader = new InputStreamReader(System.in);
            reader = new BufferedReader(streamReader);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }
    //ひたすらにメッセージ送信処理をするメソッド
    @Override
    public void run() {
        //whileがないと、一回メッセージ送ったら、接続遮断されちゃう
        while (true) {

            try {
                String data = reader.readLine();
                byte[] datas = data.getBytes();
                //送信先のIPとポート指定
                InetSocketAddress socketAddress = new InetSocketAddress(this.toIp, this.toPort);
                //パケット送信準備
                DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, socketAddress);
                //送信する
                socket.send(packet);
                if(data.equals("bye")){
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            //接続を遮断する
            socket.close();
        }
    }
}


  • メッセージ受け取る処理する
ReceiveThread.java
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;

public class ReceiveThread implements Runnable {

    DatagramSocket socket = null;
    private int receivePort;
    private String whois;

    //コネクション設立ためのメソッド
    public ReceiveThread(int receivePort, String whois) {
        this.receivePort = receivePort;
        this.whois = whois;
        try {
            //顧客問い合わせ用にこのポートで待ち受けする。
            socket = new DatagramSocket(receivePort);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    //受け取ったメッセージをひたすらに処理するメソッド
    @Override
    public void run() {
        while (true) {
            try {
                //受け取ったパケットを格納する
                byte[] datas = new byte[1024];
                DatagramPacket packet = new DatagramPacket(datas, 0, datas.length);
                socket.receive(packet);

                byte[] data = packet.getData();
                String msg = new String(data, 0, data.length);
                //受け取ったメッセージを出力
                System.out.println(whois + msg);

                if (msg.equals("bye")) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //接続を遮断する
        socket.close();
    }
}

  • 利用者

利用者は送ると受け取る両方用意する

Server.java
public class Server {
    public static void main(String[] args) {
        //顧客への回答スレッド,2222ポートからlocalhostの8888に問い合わせする
        new Thread(new SendThread(2222,"localhost",8888)).start();
        //ヘルパーからのメッセージは9999ポートで受け取る
        new Thread(new ReceiveThread(9999,"顧客")).start();
    }
}
Custumer.java
public class Custumer {
    public static void main(String[] args) {
        //顧客問い合わせするスレッド,8888ポートからlocalhostの9999に問い合わせする
        new Thread(new SendThread(7777,"localhost",9999)).start();
        //ヘルパーからのメッセージは7777ポートで受け取る
        new Thread(new ReceiveThread(8888,"ヘルパー")).start();
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0