アプリ版:「スタンプのみでお礼する」機能のリリースについて

いつもお世話になっています。
ソケットに関して質問します。

下記の手順でソケットを使用したいと考えています。
クラスAとクラスBが存在する。
1)クラスA:ソケット通信でメッセージ送信
2)クラスB:ソケット通信によるメッセージを取得
3)クラスB:ソケット通信で返信する
4)クラスA:ソケットによるメッセージを再取得する

このとき、クラスAがクラスBによるメッセージ再信が、30秒以内にこなければ、ソケットを閉じる

それにあたってソースを1クラスで実行できるよう書き変えたいのですが、どうも上手くいきません。

実行したいメソッド手順が
ソケットを開く openSocket
ソケットにメッセージ送信 sendMsg
・・・1と3はこのメソッドを使用
メッセージ取得 getMsg
・・・2と4はこのメソッドを使用
ソケットを閉じる closeSocket
の順です。

自分で一度考えてみたソースは以下です。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class Messaneger{
private Socket socket;
private BufferedReader in;

// ソケットを開く
public void openSocket() {
ServerSocket serverSocket;

try {
serverSocket = new ServerSocket(5555);
System.out.println("クライアントからの接続をポート5555で待ちます");
// クライアントからの接続を待ちます
Socket socket = serverSocket.accept();
System.out.println(socket.getInetAddress() + "から接続を受付ました");

// 出力ストリームを取得
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
// 入力ストリームを取得
in = new BufferedReader(
new InputStreamReader( socket.getInputStream()));

} catch (IOException e) {}
}

//ソケットを閉じる
public void closeSocket() {

try {
socket.close();
} catch (IOException e) {}
}

/**
* ソケット通信でメッセージを送信
* @param 送信するメッセージ
*/
public void setMsg(String sendMsg) {

try {
socket = new Socket("localhost", 5555);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
// 入力ストリームを取得
in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
//サーバーにメッセージ送信
out.println( sendMsg );

//送信メッセージdata
System.out.println(sendMsg);
} catch (IOException e) {}
}

/**
* ソケット通信でメッセージを取得
* @return msg サーバーに渡されたメッセージ
*/
public String getMsg() {
String getMsg = "";
BufferedReader in;

try {
in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
System.out.println(in.readLine());
} catch (IOException e) {}
return getMsg;
}
}

参考URL:http://www.hellohiro.com/socket.htm

宜しくお願いします。

A 回答 (3件)

askaaskaさんのおっしゃっている通り、基本的な理解が足りないんじゃないですかね。



まず、1~4について主語を付けて整理したらどうでしょう?

-----------------------------------------------------
1)クラスA:ソケット通信でメッセージ送信
2)クラスB:ソケット通信によるメッセージを取得(⇒受信)
3)クラスB:ソケット通信で返信する
4)クラスA:ソケットによるメッセージを再取得する
-----------------------------------------------------

登場人物 :
・クライアントソケット・・・socket = new Socket("localhost", 5555);
・サーバソケット・・・Socket socket = serverSocket.accept();

動作 :
・書き込む(out)
・読み込む(in)

でどうでしょうか。
    • good
    • 0
この回答へのお礼

お礼遅くなりました。

かなり、実力不足でした。
いまだに少し理解しきれていませんが、一度試して
再度もう少し勉強しなおしてまた質問させてもらいます。

回答ありがとうございました。
また、よろしくお願いします。

お礼日時:2010/04/10 17:11

これはひどい。


とりあえず、あなたのプログラミングスキルが低いことはわかったわ。
ツッコミどころをいくつか上げていくわね。

1)通信する相手は1つ。つまりSocketのインスタンスは1つあればいいのよ。
2)ストリームは通信開始時に取得して通信終了時に閉じればいいわ。
3)デバッグすれば原因はすぐわかると思うわ。
4)例外発生時はスタットレースを出したほうがいいわよ。それだけでも十分原因が絞り込めるから。
5)staticな変数がどういう意味なのか理解しているかしら?その上でこの実装をしているならいいのだけど。

とりあえずこんなところ。

この回答への補足

回答ありがとうございます。
ひとまず、高望みしすぎたので、クラスAから、Messanegerクラスにアクセスする方法を考えて作成し直してみました。
確認してもらえますでしょうか?

public class Messanger
{
private ServerSocket serverSocket;
private Socket socket;
private PrintWriter writerOut;
private BufferedReader in;

//socketを解放
public void openSocket() {
System.out.println( "--- openSocket -- ");
try {
//serverSocket = new ServerSocket(5555); //一回起動させたら、以降表示しない
socket = new Socket("localhost", 5555);
} catch (UnknownHostException e) {
System.out.println( e.getStackTrace() );
} catch (IOException e) {
System.out.println( e.getStackTrace() );
}
}

//socketを閉じる
public void closeSocket() {
try {
in.close();
writerOut.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
System.out.println( e.getStackTrace() );
}
}

//メッセージ送信
public void sendMsg(String message ) {
try{
//socketの接続状態
System.out.println("接続の有無 _ :" + this.socket.isConnected() );
// 出力ストリームを取得
writerOut = new PrintWriter(socket.getOutputStream(), true);
//出力
writerOut.println(message);
System.out.println(message);
} catch (IOException e) {
System.out.println( "send-IO:"+e.getStackTrace() );
} catch(NullPointerException e)
{
System.out.println( e.getStackTrace() );
}
}

//メッセージ取得
public String getMsg() {
System.out.println( "return _getMsg_ :" + socket.isConnected() );
String message = "";
try{
// 入力ストリームを取得
in = new BufferedReader(
new InputStreamReader(
this.socket.getInputStream()));
//戻り値に入力
message = in.readLine();
} catch (IOException e) {
System.out.println(e.getStackTrace());
} catch(NullPointerException e){
System.out.println(e.getStackTrace());
}
System.out.println("message_return:"+ message);
return message;
}
}

◆ ----- 実行するクラス ----◆
public class TestMsg {
public static void main(String[] args)
{
Messanger msn = new Messanger();
msn.openSocket();
msn.sendMsg("メッセージ送信test! ");
String returnMsg = msn.getMsg();
System.out.println( "ソケット通信されたmessage:" + returnMsg );
msn.closeSocket();
}
}

◆ ---- コンソール表示 -----◆
--- openSocket --
接続の有無 _ :true
メッセージ送信test!
return _getMsg_ :true

このとき、どうしても、値を取り出せないのですが、やはり原因は確実に【PrintWriterで出力されていない】からなのでしょうか?

宜しくお願いします。

補足日時:2010/02/03 16:36
    • good
    • 0
この回答へのお礼

お礼遅くなりました。

一度試して、もう少し勉強しなおしてわからなければ、
再度質問させてもらいます。
回答ありがとうございました。
またよろしくお願いします。

お礼日時:2010/04/10 17:13

勘違い発見。



× クラスB:ソケット通信によるメッセージを取得
○ クラスB:ソケット通信によるメッセージを受信

それはさておき

やりたいことは
HelloWorldSocketServerとHelloWorldSocketClientを
1つのクラスで書いちゃおうてことよね。
そうすれば2台のパソコンで同じクラスを実行すればよくなるから。

「うまくいかない」がどのように失敗しているのかわからないけど
多分あなたは、その参考にしているページに書かれている
HelloWorldSocketServerとHelloWorldSocketClientのコードが
理解できていないんだと思うわ。
わかっていたら少なくともあっちこちに
out=、in=は記述しないはずよ。
この2つのクラスは片方だけでソケットの送信と受信、両方とも行っているのよ。
inとoutの順序が逆なだけ。
もう一回言うわよ?
inとoutの順序が逆なだけ。
大事なので2回言ったわ。
このinから読み込むのがあなたの言うgetMsg、
outに書き込むのがsetMsgよ。

何か余計な処理をしているってこと気づけるかしら。

この回答への補足

回答ありがとうございます。
再度確認してみました。

out/inの意味はなんとか理解できたのですが、
socketから取り出す場合がどうも上手くいきません。

以下が修正ソースです。
public class Messaneger {

private static Socket socket;
private static BufferedReader in;

//ソケットを開く
public static void openSocket() {
ServerSocket serverSocket;

try {
serverSocket = new ServerSocket(5555);
System.out.println("クライアントからの接続をポート5555で待ちます");
// クライアントからの接続を待ちます
Socket socket = serverSocket.accept();
System.out.println(socket.getInetAddress() + "から接続を受付ました");

} catch (IOException e) {}
}

/**
* ソケット通信でメッセージを送信
* @param 送信するメッセージ
*/
public static void setMsg(String sendMsg) {

try {
socket = new Socket("localhost", 5555);

// 入力
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
//メッセージ設定
out.println( sendMsg );
in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
//送信メッセージdata
//System.out.println(sendMsg);
} catch (IOException e) {}
}

/**
* ソケット通信でメッセージを取得
* @return msg サーバーに渡されたメッセージ
*/
public static String getMsg() {
String getMsg = ""; //このとき上手くメッセージが取り出せない
try {
String inputLine = null;
//取り出し用の、inを設定する
in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
while (inputLine != in.readLine()) {
System.out.println("AA:"+in.readLine());
}
} catch (IOException e) {}

return getMsg;

}
}
宜しくお願いします。

補足日時:2010/02/01 23:19
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!