質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

248閲覧

SocketインスタンスはどのようにしてFileStreamインスタンスを判定しているか

paperpen

総合スコア7

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2018/04/07 02:21

編集2018/04/07 02:45

お世話になります。
Javaでネットワークプログラミングを勉強したく、書籍やインターネットの情報を参考に簡単なWebサーバを作成しようとしています。
通信自体はなんとかうまく、送受信することができました。
ですが、ふと疑問に思ったのが、ファイルの入出力処理に関してSocketの挙動で不明な点があるのです。

自分が参考にしている本やページではSocket宣言->FileStream宣言という順番でインスタンスを準備していますが、特にこれらを紐付けている処理があるようには見えませんでした。なのにgetInputStream/getOutputStreamのようにインスタンスの情報を使用しているように見えます。
また、Socketを最初に作成したのに後から作成したFileStreamの情報をSocketインスタンスがどのようにして持っているのかがわからず、質問させていただきました。

以下にソースとテンプレートにあわせた質問事項を記載いたします。
ヒントだけでもいただければとっても助かります。よろしくお願いいたします。

前提・実現したいこと

・SocketクラスがどのようにしてFileInputStream/FileOutPutStreamのインスタンスの設定を取得しているのかを理解したい

疑問点

・SocketクラスがgetInputStream/getOutPutStreamメソッドを実行した際に、どのようにして対象のストリームを決定しているかがわからない

該当のソースコード

Java

1package httpServer.server; 2 3import java.io.FileInputStream; 4import java.io.FileOutputStream; 5import java.io.IOException; 6import java.io.InputStream; 7import java.io.OutputStream; 8import java.net.ServerSocket; 9import java.net.Socket; 10 11public class TcpServer { 12 13 public static void main(String[] args) throws Exception { 14 15 // ここでSocketインスタンス宣言->FileStreamインスタンス宣言 16 try(ServerSocket server = new ServerSocket(8111); 17 FileOutputStream fos = new FileOutputStream("server_recv.txt"); 18 FileInputStream fis = new FileInputStream("server_send.txt")){ 19 20 System.out.println("クライアントからの接続を待ちます。。。"); 21 Socket socket = server.accept(); 22 System.out.println("クライアント接続!"); 23 24 int ch; 25 InputStream input = socket.getInputStream(); 26 while((ch = input.read()) != 0){ 27 fos.write(ch); 28 } 29 OutputStream output = socket.getOutputStream(); 30 while((ch = fis.read()) != -1){ 31 output.write(ch); 32 } 33 34 socket.close(); 35 System.out.print("接続を終了しました。"); 36 37 }catch (Exception e) { 38 e.printStackTrace(); 39 } 40 41 } 42 43} 44

Java

1package httpServer.client; 2 3import java.io.FileInputStream; 4import java.io.FileOutputStream; 5import java.io.IOException; 6import java.io.InputStream; 7import java.io.OutputStream; 8import java.net.Socket; 9import java.net.UnknownHostException; 10 11public class TcpClient { 12 public static void main(String args[]) throws Exception { 13 14    // こちらも同様の宣言をしている。 15 try(Socket socket = new Socket("localhost",8111); 16 FileInputStream fis = new FileInputStream("client_send.txt"); 17 FileOutputStream fos = new FileOutputStream("client_recv.txt")){ 18 19      // 処理の中で、サーバ・クライアント共にsocket.getOutputStream()/socket.getInputStream()を 20 // 呼んでいる。 21 // しかしSocketとFileInputStream/FileOutputStreamはどのタイミングで情報を結びつけたのかが不明 22 int ch; 23 OutputStream output = socket.getOutputStream(); 24 while((ch = fis.read()) != -1){ 25 output.write(ch); 26 } 27 28 output.write(0); 29 30 InputStream input = socket.getInputStream(); 31 while((ch = input.read()) != -1){ 32 fos.write(ch); 33 } 34 35 36 }catch (Exception e) { 37 e.printStackTrace(); 38 } 39 40 41 } 42} 43

試したこと

・ためしにFileInputStreamのインスタンスを二つ以上宣言してみましたが、なぜか最初のStreamが使用されました。

・デバッガにて、getOutPutStreamの処理を追いかけ、
Socket->SocketImpl->PlainSocketImpl->AbstractPlainSocketImpl->return SocketOutputStream'
といったクラスの処理の移り変わりは見ることが出来ましたが、ソースにあるような具体的なファイルパス等を確認することが出来ず、追い方がそもそもあっているのかも不明です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/04/07 02:49

変数を理解してないのでしょうか?
guest

回答1

0

ベストアンサー

多分、質問者さんに必要なのはサーバーとクライアントのコードを眺めたりデバッガーでその実装がどうなっているかを覗いたりすることではなく、通信を実現する各々のオブジェクトの役割を把握することだろうと思います。

事前に「通信とは何か」「ソケットとは何か」を把握した状態でソースコードを見れば「これらのオブジェクトは何を表すか」が推し量れるのですが事前知識なしでソースコードだけ見てもそれがわからないと思います。

「socket通信 java 仕組み」といったキーワードで図解入りで解説したような記事を探してみることをお奨めします。

例えば
http://web.sfc.keio.ac.jp/~tsaito/JavaLectures/Lecture8/Lec8-1.html
のように「いきなりソースコードを説明するのではなく通信の概念を解説するような記事」を見つけてみてください。

ちなみにSocketとFileInputStream, FileOutputStreamそれぞれに特別な関係はありません。通信を行うプログラムで肝になるのはSocketです。FileInputStraem/FileOutputStreamは通信とは直接関係ありません。このアプリケーションがたまたま通信データを扱うのにファイルを使っているだけにすぎないのです。

投稿2018/04/07 03:32

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

paperpen

2018/04/07 04:43

ご回答いただきありがとうございます! 参考として載せていただいたページ、拝見させていただきました。 自分の理解としては、TcpServerが `InputStream input = socket.getInputStream();` とした際、TcpClient側のFileInputStreamと繋がるようなイメージでしたが、 この認識であっていますでしょうか?
KSwordOfHaste

2018/04/07 04:48 編集

いえいえリンク先のページをよくご覧ください。 client側のsocketのgetOutputStream()<->server側のsocketのgetInputStream() になります。client側でwriteするとそれがサーバー側でreadできるのですから。 ---追記--- あああ!リンク先のページの記述が間違ってますね・・・失礼しました。
paperpen

2018/04/07 05:00 編集

あ、つまりこういう認識であってますでしょうか? ・サーバソケット待ち ・クライアントソケット接続要求 ・サーバとクライアントが接続 ・クライアントがOutputStream作成(try-with-resources部で確保しているストリームとは別物) ・サーバもInputStream作成(こちらも同様別物) ・ここでクライアントがtry-with-resorceで作成していたFileInputStreamを先ほど作成したストリームを通してファイル送信 ・サーバもtry-with-resourceで作成していたFileOutputStreamでファイル受信 ・逆の役割でも一度通信
KSwordOfHaste

2018/04/07 05:03 編集

そういう感じです。ちなみにOutputStream, InputStreamの「作成」というよりは「取得」と考えた方がいいです。言葉の違いは時として理解するのに重要な役割を果たすことがあります。 「作成」ならcreateOutputStreamといったメソッド名になっているはずです。そうではなくてgetOutputStreamという名前になってますね?これは「socketが接続されると自動的にOutputStreamが必要に応じて用意され、getOutputStreamはその用意されたものを取ってくるだけのメソッド」みたいな感覚でとらえると良いと思います。
paperpen

2018/04/07 05:12

>socketが接続されると自動的にOutputStreamが必要に応じて用意され、getOutputStreamはその用意されたものを取ってくるだけのメソッド」みたいな感覚 まさに自分が今回お聞きしたかったのはこの点だと思います。この説明で疑問が氷解した感があります。 getInputStreamとなっているからには、どこかからインスタンスを持ってきているのだろうと考え、それを通信相手側のFileInputStreamだと早合点してしまった点が間違いでありました。 KSwordOfHaste様、お時間割いていただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問