こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

TCPのプログラムで例外エラーが出て困っています

java eclipeを使って通信のプログラムを作ろうとしています。
参考にしている本は、TCP/IPソケットプログラミングjava編です。

本に書かれてるソースコードのとおりに入力したら、
Exception in thread "main" java.lang.IllegalArgumentException: Parameter(s): <Server> <word> [<Port>]
at socket_33.TCPEchoClient.main(TCPEchoClient.java:15)
というエラーが出ました。

このエラーを調べると、
「不正な引数、または不適切な引数をメソッドにわたしたことを示すためにスローされる」とかかれていました。
また、 <Server> <word> [<Port>] に何か文字を入力すればよいとも書かれていました。

具体的には、何を入力すればよいのでしょうか?
他のページを見て試してみても、例外エラーがとれません。

下にソースコードを載せますので、おかしな部分がありましたら、
そちらのご指導もお願いします。

package socket_33;

import java.net.*; // Socketに必要
import java.io.*; // IOException,Input/OutputStreamに必要

public class TCPEchoClient {

/**
* @param args
*/

public static void main(String[] args) throws IOException {

if ((args.length < 2) || (args.length > 3)) // 引数の数が正しいかどうかを調べる
throw new IllegalArgumentException("Parameter(s): <Server> <word> [<Port>]");

String server = args[0]; // サーバ名またはIPアドレス
// デフォルトの文字エンコード方式を使って入力Stringをバイトに変換する
byte[] byteBuffer = args[1].getBytes();

int servPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7;

// サーバの指定されたポートに接続するソケットを作成する
Socket socket = new Socket(server, servPort);
System.out.println("Connected to server...sending echo string");

InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();

out.write(byteBuffer); // エンコードされた文字列をサーバに送信する

// サーバから同じ文字列を受信する
int totalBytesRcvd = 0; // これまでに受信した合計バイト数
int bytesRcvd ; // 前回の読み込みで受信したバイト数
while (totalBytesRcvd < byteBuffer.length){
if ((bytesRcvd = in.read(byteBuffer,totalBytesRcvd,byteBuffer.length - totalBytesRcvd)) == -1)
throw new SocketException("Connection closed prenmaturely");
totalBytesRcvd += bytesRcvd;
}

System.out.println("Received: " + new String(byteBuffer));

socket.close(); // ソケットとストリームをクローズする
}
}

投稿日時 - 2009-09-25 19:49:20

QNo.5318404

すぐに回答ほしいです

質問者が選んだベストアンサー

「不正な引数、または不適切な引数をメソッドにわたしたことを示すためにスローされる」
というのだから適切な引数をメソッドにわたさないといけないのです。
とりあえずGoogleで「eclipse 引数」で検索したら
http://www.okapiproject.com/java/java_tools/eclipse/vol_2/eclipse_operation.htm#a4
こんなのが出てくる。引数ありでプログラムの実行するときの方法が書いてあるからね。
ここの例だと「サンプルプログラム」と「!」という2つの引数を渡しています。
あなたの場合だと,「サーバ名」と「サーバに渡す文字列」と「サーバのポート番号」を渡すわけだけど,

適当に3つの文字列として「127.0.0.1 telnet 80」と書けば,多分
Connected to server...sending echo string
Exception in thread "main" java.net.SocketException: Connection reset
というエラーが返るはず。

もう少しまともに書くなら,例えばあなたの使っているメールサーバを使わせてもらうことにして,「xxx.xxx.xxx.xxx HELO 25」と書けば(xxx.xxx.xxx.xxxはちゃんと調べて数字にしてね)
Connected to server...sending echo string
Received: 220
なんていう答えが返ってくるはず。

投稿日時 - 2009-09-26 15:44:21

お礼

いつも回答ありがとうございます。とても感謝しております。

127.0.0.1 telnet 80 と「プログラムの引数」の欄に入力したところ、

Exception in thread "main" java.lang.NoClassDefFoundError: TCPEchoClient
Caused by: java.lang.ClassNotFoundException: TCPEchoClient
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
Could not find the main class: TCPEchoClient. Program will exit.

また、IPアドレス test 25
と入力して実行しても上のエラーが出ました。

何がいけないのでしょうか?

投稿日時 - 2009-09-26 17:01:49

ANo.3

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(8)

ANo.8

> Received: +OK
これが返ってくるということは,入力したポート番号(多分110)はメールサーバのPOPプロトコルでアクセスするポートと言う事ですね。この場合は,こちらからどんな文字列(testとかwordとか)を送っても,まず+OKが返ってきます。これはシェルのプロンプトから
telnet メールサーバのアドレス ポート番号
とすることで確認できるでしょう。(これで接続したときはquitで終了する)

もしポート番号を25にしてsmtpでアクセスするように変更すると,引数としては
メールサーバのアドレス test 25
となって,返ってくるのは
Connected to server...sending echo string
Received: 220
となるでしょう。

なお
// サーバから同じ文字列を受信する
とプログラムのコメントに書いてありますが,これは「サーバから送った文字列と同じ文字数を受信する」の間違いでしょう。

投稿日時 - 2009-09-30 22:38:07

お礼

回答ありがとうございます。

25と入力したところ、
Connected to server...sending echo string
Received: 220
となりました。ほかのポート番号を入力して何が返ってくるか試してみようと思います。


f272さんのご指導により、このプログラムを動かすことができました。
私の質問を親切に答えてくださいまして本当にありがとうございました。

今回質問させていただきましたプログラムは、TCP/IPソケットプログラミングJava編という本の最初の章のものです。
これからこの本を進めていきます。また、分からないものがありましたら、質問を投稿させていただきます。もしお時間がございましたら教えていただきたいと思っております。

f272さん、たくさんのアドバイスありがとうございました。

投稿日時 - 2009-09-30 23:31:13

ANo.7

私はあなたのネットワーク環境を知らないので適切なアドバイスをすることは非常に困難だということは理解していますか?

> どのように確認するのでしょうか?
物理的に接続されているかから始まって,接続を邪魔するプログラム(アンチウイルスプログラムとか)が走ってないかとか色々です。で,そういうことが面倒なので,多分ちゃんと接続できているんだろうと想像したメールサーバの話をしています。

で,今問題にしているUbuntuマシンは,メールサーバにアクセスしているノートPCと同じネットワークに接続されているんですか?そのメールサーバのアドレスやポート番号はわかっているんですか?全てイエスなら,Ubuntuマシンからそれらの情報を使って接続してみてください。やり方は既に書いたとおりです。

なお,ここでメールの設定とかそんな話が出てくるとは吃驚です。関係のないプログラム(メールクライアント)でどんな設定をしていても関係ないのですから。必要なのはサーバの情報です。それを使ってあなたのプログラムでサーバに接続し,アクセスするのです。

もう1つメールサーバを使うこととは別の提案で,ウエブサーバに接続してみましょうか?
もしUbuntuマシンがインターネットに接続されているのでしたら,プログラムの引数を
okwave.jp test 80
にしてテストしてみてください。ただしこうすると
while (totalBytesRcvd < byteBuffer.length){
このループを無限に繰り返すことになりますから,プログラムを強制終了するか,そうでなければそのwhile文の直前に
System.out.println("OK");
socket.close();
System.exit(0);
を挿入して,ループに入る前にプログラムを明示的に終了させることが必要です。

投稿日時 - 2009-09-29 13:26:47

お礼

回答ありがとうございます。

ノートPCでメールサーバのアドレスとポート番号を見て、
このように引数部分に入力しました。

メールサーバのアドレス word ポート番号
すると、

Connected to server...sending echo string
Received: +OK

と表示されました。

今までは、この表示すらされなかったので、とても進歩したと思います。本当にありがとうございます。

Received: +OK
の部分ですが、ここは引数欄でwordに該当する文字列が出力されると思っていましたが違うのでしょうか?

私は、引数の欄には、testと入力していました。
ほかにもwordと入力してもReceived: +OKとなります。

何を入力してもReceived: +OKとなるのでしょうか?

投稿日時 - 2009-09-30 21:16:53

ANo.6

> このプログラムはおかしいですか?
プログラムがおかしいんじゃなくて,動作環境がおかしいんでしょ。
このプログラムを実行している機械から,ちゃんと指定したサーバの指定したポートに接続できるの?それを確認してくださいね。
または,もともと接続が確認できているサーバとポートを見つけてきてそれを指定してもいいよね。この方針だと,以前にも言ったけど,例えば自分の使っているメールサーバがあるでしょ。で,その機械からメールサーバに対してメールを送ることができるよね。こういう状況ならそのメールサーバに対して接続要求をするようにすれば良いわけで,メールサーバなら25番ポートでsmtpプロトコルが使えてHELOと挨拶すれば返事をくれると思うので
xxx.xxx.xxx.xxx HELO 25
と指定してみたらどうでしょう,と提案した次第です。
とにかく接続ができる環境で,プログラムを実行してくださいね。

投稿日時 - 2009-09-28 12:12:52

お礼

回答ありがとうございます。いつもすみません。

>このプログラムを実行している機械から,ちゃんと指定したサーバの
>指定したポートに接続できるの?それを確認してくださいね。

どのように確認するのでしょうか?

私は、Ubuntuでプログラミングをしています。メールはノートPCで行うので、Ubuntu(プログラムを動かしている機械)のメールの設定はしていません。

このメールの設定をしていない機械(Ubuntu)ではメールサーバに接続要求をすることはできないのでしょうか?プログラムをちゃんと実行させるためには、メールの設定をする必要がありますか?

投稿日時 - 2009-09-28 22:48:54

ANo.5

Exception in thread "main" java.net.ConnectException: Connection refused
ということは文字通り接続を拒否されているのです。
サーバ名は127.0.0.1にしてる?
本当に127.0.0.1が存在する?環境が分からないけど,例えばシェル(コマンドプロンプト)からping 127.0.0.1としてエラーにならない?

まあ,127.0.0.1でなくてもちゃんと存在して自分が接続できるはずのサーバのアドレスを指定してやれば,少なくともConnected to server...sending echo stringは出てくると思うよ。

投稿日時 - 2009-09-26 22:13:36

お礼

回答ありがとうございます。

コマンドプロンプトでping 127.0.0.1と入力すると、
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.017 ms
となりました。

サーバ名を127.0.0.1にして実行しましたが同じエラーです。
質問当初とはソースコードを少し変えたので、下に載せます。
このプログラムはおかしいですか?

package socket_33;

import java.net.*; // Socketに必要
import java.io.*; // IOException,Input/OutputStreamに必要

public class TCPEchoClient {
public static void main(String[] args) throws IOException {

if ((args.length < 2) || (args.length > 3)) // 引数の数が正しいかどうかを調べる
throw new IllegalArgumentException("Parameter(s): <127.0.0.1> <test> [<25>]");

String server = args[0]; // サーバ名またはIPアドレス
// デフォルトの文字エンコード方式を使って入力Stringをバイトに変換する
byte[] byteBuffer = args[1].getBytes();

int servPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7;

// サーバの指定されたポートに接続するソケットを作成する
Socket socket = new Socket(server, servPort);
System.out.println("Connected to server...sending echo string");

InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();

out.write(byteBuffer); // エンコードされた文字列をサーバに送信する

// サーバから同じ文字列を受信する
int totalBytesRcvd = 0; // これまでに受信した合計バイト数
int bytesRcvd ; // 前回の読み込みで受信したバイト数
while (totalBytesRcvd < byteBuffer.length){
if ((bytesRcvd = in.read(byteBuffer,totalBytesRcvd,byteBuffer.length - totalBytesRcvd)) == -1)
throw new SocketException("Connection closed prematurely");
totalBytesRcvd += bytesRcvd;
}

System.out.println("Received: " + new String(byteBuffer));

socket.close(); // ソケットとストリームをクローズする
}
}

投稿日時 - 2009-09-27 02:45:05

ANo.4

あなたのエラーを見ると
Could not find the main class: TCPEchoClient. Program will exit.
といわれているようだけど,メインクラスは
socket_33.TCPEchoClient
のはずじゃなかったの?もしかすると#3であげたページを見て変えちゃったのかな?

投稿日時 - 2009-09-26 21:24:20

補足

もうしわけございません。
ソースコードの
/**
* @param args
*/
の部分をけしていたため、行の数字が変わっていました。

実際は24行目がおかしいというメッセージが出ています。
この部分です。
Socket socket = new Socket(server, servPort);

投稿日時 - 2009-09-26 21:53:38

お礼

回答ありがとうございます。

はい、変えてしまいました。
メインクラスをsocket_33.TCPEchoClient
としたところ、違うエラーが出ました。

Exception in thread "main" java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(Unknown Source)
at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at socket_33.TCPEchoClient.main(TCPEchoClient.java:19)

調べたら、ソケットの接続を試行中にエラーが発生したことの
通知だと書いてありました。

19行目のなにがおかしいのでしょうか?

投稿日時 - 2009-09-26 21:49:00

ANo.2

ちょっとeclipseをインストールしてみた#1です。
同じエラーが出るということは,全く引数が渡されていないということ。

> 「サーバ名」…IPアドレス
> 「サーバに渡す文字列」…word
> 「サーバのポート番号」…123
> としました。

具体的に何をしたのかな?
Run(実行) - Run Configurations...(実行) で出てくるダイアログでMain(メイン)タブのところではなく,Arguments(引き数)タブのProgram arguments(プログラム引き数)にちゃんと書き込んでいるのかな?

投稿日時 - 2009-09-25 21:30:16

補足

プログラム引数の欄にはどのように書けばよいのでしょうか?

投稿日時 - 2009-09-25 23:19:26

お礼

15行目のthrow new IllegalArgumentException("Parameter(s): <Server> <word> [<Port>]");の部分に
<IPアドレス> <word> [<123>]");としただけです。

>Run(実行) - Run Configurations...(実行) で出てくるダイアログで
>Main(メイン)タブのところではなく,Arguments(引き数)タブの?
>Program arguments(プログラム引き数)にちゃんと書き込んでいるのか
>な?

書き込んでいません。

投稿日時 - 2009-09-25 23:04:19

ANo.1

このプログラムが何をするプログラムなのか理解しているのだろうか?

まあ,何も分かっていなくても
TCPEchoClient.java:15
と書かれているのだから,15行目をみて
throw new IllegalArgumentException("Parameter(s): <Server> <word> [<Port>]");
と書いてあるところに注目するよね。そうすると確かに
java.lang.IllegalArgumentException
が呼ばれていて
Parameter(s): <Server> <word> [<Port>]
を返すことになっている。これが呼ばれる条件は
if ((args.length < 2) || (args.length > 3))
なのだから引数の数を2か3にすればよい。で,期待されている引数は書いてある通り
「サーバ名」と「サーバに渡す文字列」と(オプショナルに)「サーバのポート番号」
だと分かる。

ついでに
throw new SocketException("Connection closed prenmaturely");
これは,エラーにはならないが
throw new SocketException("Connection closed prematurely");
の間違いだろう。

投稿日時 - 2009-09-25 20:08:29

お礼

回答ありがとうございます。

「サーバ名」…IPアドレス
「サーバに渡す文字列」…word
「サーバのポート番号」…123

としました。これで実行しても同じエラーが出ます。
なにがいけないのでしょうか?

投稿日時 - 2009-09-25 20:46:14

あなたにオススメの質問