ソケットとストリームの関係について

このQ&Aのポイント
  • ソケットとストリームは1対1の関係にありますか?
  • ソケット通信でクライアントからの接続を受ける際、StreamやReader/Writerなどを作成していますが、1つのクライアントに対して2つのストリームが作成されるのでしょうか?
  • ストリームをクローズする際にエラーが発生することがありますが、新たに作成したストリームは古いストリームを使いまわしているのでしょうか?
回答を見る
  • ベストアンサー

ソケットとそれに基づくストリームは1対1でしょうか。

ソケット通信で、接続してきた クライアント(TcpClient tempclient)から、 NetworkStream,StreamReader,StreamWriterなどを 作っています。 Class A while(true){ tcpclient=server.AcceptClient(); networkstream=tcpclient.getStream(); streamreder=new StreamReader(networkstream...); mythread=new Mythread(tcpclient); // networkstream.close() streamreader.close() //これらを加えると、下の、/* */でエラーになります。 } MyThread B { Public Mythread(TcpCLient tcpclient){ /* ns=tcpclient.Getstream sr=... */ } このクライアントを、別のスレッドで使うため、 mythread=new MyThread(tcpclient)などとして、 別のクラスにもっていき、 そこでも、新たに、NetworkStream,StreamReaderを 作ったとします。 この場合、1つのクライアントにつき、2つの ストリームができるのでしょうか。 経験上、ストリームを作成するコードは 問題なく動きます。 しかし、新たにストリームを得たので、古いのを クローズすると、エラーになります。 新たに作ったストリームは、実は、古いストリームを、 使いまわしていることになるのでしょうか。 少し、分かりづらいかもしれませんが、 何か分かる人がいましたら、よろしくお願いします。

  • rheda
  • お礼率69% (257/372)

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

  • ベストアンサー
  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.1

具体的にどんなクラスを使っているのかよく分かりませんが、常識的な実装をしているならストリームをクローズするときには対応するソケットを破棄しているでしょう。ストリームをクローズせずに廃棄(delete)すると上手くいくかもしれませんが、デストラクタがクローズすることも考えられるので上手くいく保証はありません。 使っているストリームクラスにソケットとの関係を切断する機能が実装されていれば良いですが、そうでなければソケットとストリームは一対一で使うことが前提になると思います。

rheda
質問者

お礼

回答ありがとうございます。 貴重な意見で、非常に参考になりました。 一体のものとして、扱っていきたいと 思います。

関連するQ&A

  • C# 半角カナの文字化けについて

    こんにちは。 現在、Visual Studio 2005 C#を使っています。 ネットワーク経由で機器の情報を取得しようとしているのですが、文字化けが起きてしまいました。 調べてみると'c0','b2','d1'と帰ってきていて、これらはS-jis半角カナの'タ','イ',’ム’を表しているようです。 少し省略していますが以下のような手順で確認しています private void buttonStart_Click(object sender, EventArgs e) { TcpClient client = new TcpClient(textBoxIP.Text,int.ParstextBoxPort.Text)); NetworkStream netStream = client.GetStream(); StreamReader sr = new StreamReader(netStream); StreamWriter sw = new StreamWriter(netStream); sw.AutoFlush = true; sw.WriteLine("TestCommand"); string s = sr.ReadLine();//ここで文字化け } StreamReader,StreamWriterの設定でEncoding指定が出来るようですが、sjisは無かったように思いました。 (defaultはUTF-8になっているようですので文字化けしたようです。) どのようにすれば、sjisで文字列を取得できるでしょうか?

  • クライアント上のC++でサーバーとソケット送信

    クライアント(Windows7)上でC++を使って、サーバー側(Windows)に対してデータを送りたいです (ソケット通信?)。 サーバ受信側はC#を使ったプログラムで以下のような感じで考えてます。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.IO; namespace ConsoleApplication1 {   class Program   {     static void Main(string[] args)     {       int port = 2222;       System.Net.IPAddress ip = IPAddress.Parse("127.0.0.1");       System.Net.Sockets.TcpListener server = new TcpListener(ip, port);       Console.WriteLine("Enter押してください");       ConsoleKeyInfo info = Console.ReadKey();       if (info.Key == ConsoleKey.Enter)       {         Console.WriteLine("サーバー待機中");         server.Start();         TcpClient client = server.AcceptTcpClient();         NetworkStream ns = client.GetStream();         StreamWriter sw = new StreamWriter(ns);         Console.WriteLine(sw);       }     }   } } C++のことがよくわかってないので、送信側でC++を使ってどのように 送信すればいいのかわかりません。 送信するデータはINT型で、1秒間に1回、繰り返し送ります。 よろしくお願いします。

  • POP before SMTPのメール

    ASP.NETでメールの送信を行うWebアプリケーションを試作しております。 POP before SMTPのPOPサーバ認証に失敗しています。 [環境] OS WindowsXP Pro サーバ IIS [ボタン押下時] ================== '接続 Dim pop As TcpClient = New TcpClient(Server, 110) Try Dim NwStm As NetworkStream = pop.GetStream() Dim rdStm As StreamReader = New StreamReader(NwStm, System.Text.Encoding.ASCII) Dim wrStm As StreamWriter = New StreamWriter(NwStm, System.Text.Encoding.ASCII) Try '接続メッセージ確認 res = rdStm.ReadLine() 'ユーザー情報送出 message = "USER " + UserId wrStm.WriteLine(message) wrStm.Flush() 'レスポンス取得 res = rdStm.ReadLine() 'パスワード送出 message = "PASS " + Passwd wrStm.WriteLine(message) wrStm.Flush() res = rdStm.ReadLine() '接続終了 wrStm.WriteLine("QUIT") wrStm.Flush() Finally NwStm.Close() End Try Finally pop.Close() End Try 'ここからメール送信 ・ ・ ・ ================== ビルドの際エラーは出ず、ボタンクリック時に、以下のエラーが出ます。 ================== 接続済みの呼び出し先が一定の時間を過ぎても正しく応答しなかったため、接続できませんでした。 または接続済みのホストが応答しなかったため、確立された接続は失敗しました。 Dim pop As TcpClient = New TcpClient(Server, 110) ←エラー箇所 ================== 似たプログラムを書いたことのある方、何か情報をお持ちの方、よろしければアドバイスを頂きたく思います。よろしくお願いします。

  • C# StreamReader,StreamWriter による文字化

    C# StreamReader,StreamWriter による文字化け お世話になります。 文字化けで悩んでいます。 Visual Studio 2008 C# にて、テキストファイルからデータを読んで別のテキストファイルに そのまま書き出す(もちろん実際の運用では加工するわけですが)処理で文字化けが起こります。 そのテキストファイル自身を C# で作れば問題はないのですが、メモ帳を使って書き込んだファイルでは 文字化けが起こります。 対処方法があれば教えてください。 以下はその実験に使ったコードです。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace ConsoleApplication5 { class Program { static void Main(string[] args) { // これは正常に書き込みできました StreamWriter sw = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\test.txt"); sw.WriteLine("これはてすとです。"); sw.WriteLine("This is test."); sw.Close(); // これも正常に読み込め、書き込みもできました StreamReader sr = new StreamReader(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\test.txt"); sw = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\newtest.txt"); while (!sr.EndOfStream) { sw.WriteLine(sr.ReadLine()); } sr.Close(); sw.Close(); // 次はあらかじめメモ帳で作ったファイルを読んで、別のファイルに書き出します // これが文字化けします sr = new StreamReader(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\test2.txt"); sw = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\newtest2.txt"); while (!sr.EndOfStream) { string dat = sr.ReadLine(); sw.WriteLine(dat); Console.WriteLine(dat); } sr.Close(); sw.Close(); } } }

  • C#で通信処理。応答がない場合、すぐエラーにしたい

    VS2005、C#で通信処理をしています。 やりたいことは「接続後、データを渡してその返答データをもらう」です。 //サーバーに接続 Int32 port = 9999; TcpClient client = new TcpClient(server, port); //サーバーにメッセージを送信 Byte[] dataA = System.Text.Encoding.UTF8.GetBytes(message); Byte[] dataB = Byte[128]; NetworkStream stream = client.GetStream(); stream.Write(dataA, 0, dataA.Length); len = stream.Read(dataB, 0, dataB.Length) client.Close(); ネットのサンプルを参考にさせてもらい、上のようなソースを作ることができたのですが、2つの疑問があります。 (1)接続時に指定したIPアドレスが存在しない場合、エラーが返ってくるのが遅いです。そういうものなのでしょうか。たとえば、即時返答などはできないのでしょうか。 (2)接続してデータを送っても、向こうからデータが返ってこなければずっと待機したままです。たとえばミリセカンドで切ることはできないのでしょうか。 もしくは指定のミリセカンド経過後強制的にエラー処理に飛ばす等はできないのでしょうか。 通信処理をやるのが初めてで定石がよくわからず、あれこれ試している状態です。 処理についてご存じの方、ご指南いただけたらと思います。参考になるサイトや検索キーワードだけでも教えていただけたら嬉しいです。 よろしくお願いします。

  • 初歩的なソケット通信(java)

    初歩的なソケット通信(java) javaのソケット通信プログラムについて質問させて頂きます。まだまだ基礎の段階なのですが、詰まってしまたので、良かったら教えてください。 以下プログラムコード ------------------------------------- //サーバー側 import java.net.*; import java.io.*; public class Server { static int port = 12345; public static void main(String[] args) { try{ //サーバソケットの作成 ServerSocket ssoc = new ServerSocket(port); //メインループ while(true){ try{ System.out.println("クライアントからの接続を"+ port +"で待ちます"); Socket soc = ssoc.accept(); System.out.println(soc.getInetAddress().getHostName()+"から接続を受けました"); //処理をスレッドに任せます new Connect(soc); }catch(IOException e1){ e1.printStackTrace(); } } }catch(IOException e2){ e2.printStackTrace(); } } } class Connect extends Thread{ private Socket socket = null; public Connect(Socket socket){ this.socket = socket; //スレッド開始 this.start(); } public void run(){ try{ //出力ストリームを取得 OutputStream os = socket.getOutputStream(); PrintWriter out = new PrintWriter(os,true); //入力ストリームを取得 InputStream is = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader in = new BufferedReader(isr); String inputLine; while((inputLine = in.readLine()) != null){ //System.out.println(inputLine); out.println(inputLine); } System.out.println("処理が終わったので接続を切ります"); in.close(); out.close(); socket.close(); }catch(Exception e1){ try{ socket.close(); }catch(Exception e2){ e2.printStackTrace(); } } } }

  • ASP.NET C#で

    ASP.NET C#で重複登録されないようにStreamReaderで読み込んで確認後重複がなければ StreamWriterで書き込むというプログラムを書いていたのですが、重複確認もcsvファイルへの書き込むもエラーが表示されて出来ませんでした。 sr.Close();の位置を変えても変わりませんでした。 エラー内容 ・System.ObjectDisposedException はユーザー コードによってハンドルされませんでした。 Message=閉じている TextReader から読み取ることはできません。 他にも、他のプロセスに使われているため・・・と言ったエラーも表示されます。 ソースコード protected void Button1_Click(object sender, EventArgs e) { string Searchid = TextBox1.Text;//商品コード //ファイルの存在を確認 if (!File.Exists(MapPath(".") + "\\Data\\product.csv")) { Label2.Text = "データ登録先が存在しません。管理者に連絡してください。"; return; } this.Label1.Text = string.Empty; //確認ここまで StreamReader sr = new StreamReader(MapPath(".") + "\\Data\\product.csv", true); while (sr.Peek() != -1) { string date = sr.ReadLine(); char[] delimiter = new char[] { ',' }; string[] item = date.Split(delimiter); string id = item[0]; sr.Close(); if (Searchid.Equals(id)) { Label1.Text = "既に存在する商品コードです。別の商品コードを指定してください。"; } else { Session["scode"] = TextBox1.Text;//商品コード Session["sname"] = TextBox2.Text;//商品名 Session["price"] = TextBox3.Text;//価格 StreamWriter sw = new StreamWriter(MapPath(".") + "\\Data\\product.csv", true, Encoding.GetEncoding("Shift_jis")); sw.WriteLine(TextBox1.Text + "," + TextBox2.Text + "," + TextBox3.Text);//商品コード+商品名+単価 sw.Close(); Label1.Text = "正常に登録出来ました。"; } } } どのようにしたら実行出来るのでしょうか? 教えて下されば幸いです。

  • 簡単なネットワークプログラムなのですが・・・

    ネットワーク通信の基礎を学ぼうと、いろいろなサイトをみながらSocket通信の簡単なメッセージ送受信を行おうとしているのですが、streamを使って送信したメッセージを送信、又は受信するときにsocketを閉じないと送信できません。 そして常に受信させたいのですが、socketを閉じているため、nullexceptionになってしまいます。 何か別の手はありますでしょうか・・・? 現在↓のような感じで行っています。 private void 待機ToolStripMenuItem_Click(object sender, EventArgs e) { //サーバーを開始 Int32 port = 9999; IPAddress localAddr = IPAddress.Parse("127.0.0.1"); server = new TcpListener(localAddr, port); server.Start(); threadA = new Thread(recvData); threadA.Start(); } // 受信用(マルチスレッド) public void recvData() { //接続待機 this.Invoke(new MyDelegate(delegate { textBox1.Text = "接続待機中"; })); TcpClient client = server.AcceptTcpClient(); //接続 this.Invoke(new MyDelegate(delegate { textBox1.Text = "接続されました"; })); NetworkStream stream = client.GetStream(); // 無限ループ while (true) { Byte[] bytes = new Byte[20]; //わざと小さく取ってある。 int i; //メッセージを受信 while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) { String data = System.Text.Encoding.UTF8.GetString(bytes, 0, i); Console.WriteLine(String.Format("受信: {0}", data)); } client.Close(); }

  • TCP/IP通信でのコネクションロスト(ソケットエラー)の検知について

    インターネット上での対戦ゲームの作成を行なっているところです。 サーバーを挟んでクライアント間で双方向の通信を行なっています。  A → サーバー → B  A ← サーバー ← B TCP/IPは信頼性の高い通信方法ということで、データ抜けなどは 心配しなくても良いと聞いています。 もし、データ抜けなどが発生した場合はコネクションロストの状態になると。 実際のプログラミングではソケットを使用しています。 コネクションロストが起きると、ソケットエラーかソケットクローズで検知できます。 実際に例えばクライアントAを強制終了させるとサーバーはただちに ソケットクローズを検知します。 ここで、問題はデータを送っても届かないのに、 ソケットエラーもソケットクローズも起きない状態が発生することです。 これはインターネットの経路上になにか問題が発生したと考えていますが このような状態はタイムアウトなどで監視する以外に検知する方法はないのでしょうか? クライアントはウィンドウズでVB6.0のwinsockを、 サーバーはLinuxを使用しています。 なにかアドバイスをいただければありがたいです。

  • ソケット通信について

    自分はJAVAで、クライアント・サーバ形式の ネットワークゲームを作ろうとしているのですが、 チャットシステムで BufferedReader NetInput; // ネットワーク経由入力ストリーム PrintStream NetOutput; // ネットワーク経由出力ストリーム Socket socket; // ソケット ChatServer chatserver; // ChatServerオブジェクト int clientnumber; // クライアント番号 ChatClient(Socket socket, ChatServer chatserver, int clientnumber) { this.socket = socket; this.chatserver = chatserver; this.clientnumber = clientnumber; try { InputStream inputstream = socket.getInputStream( ); NetInput = new BufferedReader(new InputStreamReader(inputstream)); OutputStream outputstream = socket.getOutputStream( ); NetOutput = new PrintStream(outputstream); } catch(Exception e) { System.out.println("->" + e); } } // メッセージ送信 ------------------------ synchronized void sendMessage(String message) { NetOutput.println(message); // サーバからクライアントに送信 NetOutput.flush( ); } とString型の文字列messageを送受信し合う様に、 int型の配列や、boolean型の配列を送受信する方法があったら 教えていただきたいです。

専門家に質問してみよう