javaでチャットアプリを作ろうと思い,CUIでチャットサーバーをjavaFXを使用してチャットクライアントを作成しました.チャットサーバーの方はメッセージを受信,送信を送るものをスレッドで表現しています.GUIの方のソースコードではconnectボタンをクリックするとソケットの接続とメッセージの受信を行い,中央のテキストエリアにサーバーから送られたメッセージを表示するスレッドと送信ボタンをクリックするとテキストフィールドに入力されている文字をサーバーに送信するスレッドを作成してそれらをイベント発生時に開始するようなものを作成しました.
しかし,問題が二つ発生してしまいました
- サーバーに送信できない
- sendボタンをクリックしてしまうとテキストフィールドに文字が入力できなくなる
このうちのサーバーに送信する問題は解決できたのですが下の問題が解決できません
原因がわからないので教えてください
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class ChatServer { static int port = 1000; public static void main(String[] args) { try{ @SuppressWarnings("resource") ServerSocket server = new ServerSocket(port); Socket socket = null; System.out.println("開始します"); while(true){ try{ socket = server.accept();//接続要求を待つ //スレッド生成 ChatServerThread thread = new ChatServerThread(socket); thread.start(); }catch (IOException e){ } } }catch(IOException e){ System.out.println(e); } } } ```チャットサーバースレッド import java.io.*; import java.net.*; import java.util.*; public class ChatServerThread extends Thread{ static int port = 1000; static Vector<ChatServerThread> threads;//動作中のスレッドの集合 Socket socket;//クライアントに対するソケット String nickname = null; public ChatServerThread(Socket s){ super(); socket = s; if(threads == null) threads = new Vector<ChatServerThread>();//Threadsの初期化 threads.add(this);//自分自身を追加 } public String getNickname(){ return this.nickname; } public void run(){ try{ System.out.println("Connect"); InputStream is = socket.getInputStream(); DataInputStream dis = new DataInputStream(is); OutputStream os = socket.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); dos.writeUTF("Connect");//接続したのを送信する while(true){ try{ String message = dis.readUTF(); System.out.println(message); if(message == null){ socket.close(); threads.remove(this);//スレッドを削除 return;//スレッド消滅 } if(message.startsWith("NICK:")){ StringTokenizer st = new StringTokenizer(message,":"); st.nextToken();//NICKの後のトークンをニックネームとする nickname = st.nextToken(); dos.writeUTF("Hello"+nickname+"! You entered.\r\n"); dos.flush(); } else{ if(nickname != null){//ニックネームが登録されている場合 chat(message); }else{//ニックネームが登録されてない場合のエラー dos.writeUTF("Error! あなたはニックネームを入力していない"); dos.flush(); } } } catch(IOException e){ e.getMessage(); socket.close(); threads.remove(this); return; } } }catch(IOException e){ System.out.println(e); } } public void chat(String message){ for(int i = 0;i < threads.size();i++){ ChatServerThread thread = (ChatServerThread)threads.get(i); if(thread.isAlive()){ thread.talkone(this,message); } } System.err.println(getNickname() + ":" + message); } public void talkone(ChatServerThread talker,String message){ try{ OutputStream os = socket.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); String nick = talker.getNickname(); if(talker == this){ dos.writeUTF("[" + nick + "]" + message +"\r\n"); }else { dos.writeUTF("<" + nick + ">" + message + "\r\n"); } dos.flush(); }catch(IOException e){ System.out.println(e); } } }
package application; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.TextArea; import javafx.scene.control.TextField; public class SampleController { @FXML TextField inputAdress; @FXML TextField inputPort; @FXML TextArea displayMessage; @FXML TextField sendMessage; @FXML Button buttonConnect; @FXML Button buttonDisconnect; @FXML Button buttonSendMessage; private NetConnectTask taskConnect; private NetSendMessageTask taskSendMessage; Socket socket; @FXML protected void handleButtonConnectAction(ActionEvent event){ String adress = inputAdress.getText(); int port = Integer.parseInt(inputPort.getText()); socket = new Socket(); // 指定されたホスト名(IPアドレス)とポート番号でサーバに接続する try{ socket.connect(new InetSocketAddress(adress, port)); }catch(IOException e){ displayMessage.setText(e.getMessage()); } taskConnect = new NetConnectTask(socket); displayMessage.textProperty().bind(taskConnect.messageProperty()); Thread thread = new Thread(taskConnect); thread.setDaemon(true); thread.start(); } @FXML protected void handleButtonDisconnectAction(ActionEvent event){ taskConnect.cancel(); taskSendMessage.cancel(); sendMessage.textProperty().unbind(); displayMessage.textProperty().unbind(); } @FXML protected synchronized void handleButtonSendMessageAction(ActionEvent event) { taskSendMessage = new NetSendMessageTask(socket,sendMessage.getText()); sendMessage.textProperty().bind(taskSendMessage.messageProperty()); Thread thread = new Thread(taskSendMessage); thread.setDaemon(true); thread.start(); } }
package application; import java.io.DataInputStream; import java.io.InputStream; import java.net.Socket; import javafx.concurrent.Task; public class NetConnectTask extends Task<Void> { private Socket socket; protected NetConnectTask(Socket socket){ this.socket = socket; } @Override protected Void call() throws Exception { // 接続されたソケットの入力ストリームを取得し,データ入力ストリームを連結 InputStream is = socket.getInputStream(); DataInputStream dis = new DataInputStream(is); while(socket != null){ if(isCancelled()){ socket.close(); break; } // データの受信 String message = dis.readUTF(); updateMessage(message+"\n"); } return null; } }
package application; import java.io.*; import java.net.Socket; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.concurrent.Task; public class NetSendMessageTask extends Task<Void>{ private Socket socket; private StringProperty message = new SimpleStringProperty(); protected NetSendMessageTask(Socket socket,String message){ this.socket = socket; this.message.set(message); } @Override protected Void call() throws Exception { // 接続されたソケットの出力ストリームを取得し,データ出力ストリームを連結 OutputStream os = socket.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); while(socket != null){ if(isCancelled()){ socket.close(); break; } // データの送信 dos.writeUTF(message.toString()); updateMessage(""); } return null; } }
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.*?> <?import java.lang.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.layout.GridPane?> <GridPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="application.SampleController"> <columnConstraints> <ColumnConstraints /> <ColumnConstraints /> <ColumnConstraints /> <ColumnConstraints /> </columnConstraints> <rowConstraints> <RowConstraints /> <RowConstraints /> <RowConstraints /> <RowConstraints /> </rowConstraints> <children> <Label prefHeight="17.0" prefWidth="54.0" text="IPadress:" /> <TextField fx:id="inputAdress" GridPane.columnIndex="1" /> <Label prefHeight="17.0" prefWidth="53.0" text="Port:" GridPane.rowIndex="1" /> <TextArea fx:id="displayMessage" prefHeight="200.0" prefWidth="187.0" GridPane.columnSpan="4" GridPane.rowIndex="2" /> <TextField fx:id="inputPort" GridPane.columnIndex="1" GridPane.rowIndex="1" /> <TextField fx:id="sendMessage" GridPane.columnSpan="3" GridPane.rowIndex="3" /> <Button fx:id="buttonConnect" mnemonicParsing="false" onAction="#handleButtonConnectAction" text="connect" GridPane.columnIndex="2" GridPane.rowIndex="1" /> <Button fx:id="buttonDisconnect" mnemonicParsing="false" onAction="#handleButtonDisconnectAction" text="disconnect" GridPane.columnIndex="3" GridPane.rowIndex="1" /> <Button fx:id="buttonSendMessage" mnemonicParsing="false" onAction="#handleButtonSendMessageAction" prefHeight="25.0" prefWidth="73.0" text="Send" GridPane.columnIndex="3" GridPane.rowIndex="3" /> </children> </GridPane>

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/12/31 00:23 編集
2016/01/01 05:01