ネットワーク通信の基礎を学ぶための簡単なプログラムでSocket通信を行おうとしていますが、送信したメッセージを受信する際にsocketを閉じないと送信できません。解決策はありますか?

このQ&Aのポイント
  • ネットワーク通信の基礎を学ぶために、Socket通信の簡単なメッセージ送受信を行おうとしています。しかし、streamを使って送信したメッセージを受信する際にsocketを閉じないと送信できません。
  • 常に受信させたいため、socketを閉じているとnull例外が発生してしまいます。この問題を解決するための手段はありますか?
  • 現在のプログラムでは、サーバーを開始して待機し、クライアントとの接続後にメッセージの受信を行っています。受信時にはstreamを使ってデータを読み込みます。
回答を見る
  • ベストアンサー

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

ネットワーク通信の基礎を学ぼうと、いろいろなサイトをみながら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(); }

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

  • ベストアンサー
  • reset_cat
  • ベストアンサー率68% (94/138)
回答No.3

とりあえず作ってみました。エラー処理等は入っていません。 これを2つ起動して片方サーバに、もう片方をクライアントにすればいけると思います。 public partial class Form1 : Form { delegate void SetTextMessageHandler(String strMessage); SetTextMessageHandler eventRead; Thread threadRead; TcpListener tcpListener; TcpClient tcpClient; NetworkStream clientStream; public Form1() { InitializeComponent(); eventRead = new SetTextMessageHandler(setTextMessage); } private void threadStartWork() { if (tcpListener == null) { tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 30001); tcpListener.Start(); TcpClient tcpServer = tcpListener.AcceptTcpClient(); NetworkStream serverStream = tcpServer.GetStream(); Byte[] aryBuffer = new Byte[100]; int nRead = serverStream.Read(aryBuffer, 0, aryBuffer.Length); while (nRead > 0) { Object[] aryArgs = new Object[1]; aryArgs[0] = Encoding.UTF8.GetString(aryBuffer, 0, nRead); this.Invoke(eventRead, aryArgs); nRead = serverStream.Read(aryBuffer, 0, aryBuffer.Length); } } } private void setTextMessage(String strMessage) { textBox1.Text = strMessage; } private void button1_Click(object sender, EventArgs e) // 待受 { threadRead = new Thread(new ThreadStart(threadStartWork)); threadRead.Start(); } private void button2_Click(object sender, EventArgs e) // 接続 { tcpClient = new TcpClient(); tcpClient.Connect(IPAddress.Parse("127.0.0.1"), 30001); clientStream = tcpClient.GetStream(); } private void button3_Click(object sender, EventArgs e) // 送信 { Byte[] aryBuffer = Encoding.UTF8.GetBytes(textBox1.Text); clientStream.Write(aryBuffer, 0, aryBuffer.Length); } }

uryotti
質問者

お礼

ありがとうございました! 参考にさせていただきます!

その他の回答 (2)

  • reset_cat
  • ベストアンサー率68% (94/138)
回答No.2

このコードはC#の簡易ソケット通信のサーバ側ですね。#1さんの言うように、言語環境などが書いてないと回答する方も回答できないでしょう。 で、送信できないということは、最初にクライアント側に問題があると考えると思うのですが、そのクライアント側のコードがないので、どこに問題があるのかがわかりません。 まずはクライアント側のコードを補足されてみては?

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.1

ソースのネストが全部つぶれてるためコード見るのが苦痛で あまりちゃんと見てませんが使ってる環境(コンパイラ・OS)は何でしょうか? 個人的に見慣れない環境のような気がしてるんですが (XPでVC6++環境の知識なので根本違ったらごめんなさい) 作ってるのはサーバ・クライアント両方ですか? サーバのほうで言えばLisn(だっけ?)接続待ちしてるのが どこか分かりませんがservrt.start() 関数なのでしょうか? 接続語コネクション張らないといけないはずですが そのあたりのコードが一切見当たらない気がします もしVC系統使われているのであればソケット通信の サンプルプログラムがCDにあるのではないかと思いますが (VC6にはあります) Socket通信の作り的には全てイベント定義の形で ソケット操作するはずです ACCEPT/READ/WRITE/CLOSE 全てイベントが飛ぶので 無限ループなんか作る必要ないはずです

関連するQ&A

  • Thread.Abortメソッド後の処理について

    Thread.abortメソッドについて分からないことがあったので,助言が頂けると嬉しいです. Thread.Abort () を発生させると,通常そこでスレッドが終了するということなので,その後のスレッド内の処理はスルーされると思っていたのですが,下記コードですとその後の pictureBox1.Image = null;も実行されている様です. mainでスレッド作成→threadAの停止になると考えていたのですが,delegate内では反映されないのでしょうか? Thread thread_a; //スレッド delegate void Del(); private void main(object sender, EventArgs e) { //スレッドを開始 thread_a = new Thread(new ThreadStart(threadA)); thread_a.Start(); } private void threadA() { new Thread(new ThreadStart(delegate { Invoke((Del)delegate { thread_a.Abort(); //画像を消去する pictureBox1.Image = null; }); })).Start(); }

  • javaプログラム初心者です。

    入力ファイルの内容をWebサーバプログラムへ送信し、サーバからの応答を別ファイルに出力するクライアントプログラムを作っているのですが、出力ファイルにはなにも書き込みがされていません。(サーバからの応答は事前に不明でその長さが可変長である) 以下が作ったプログラムです。間違っているところを詳しくご指摘いただけるとありがたいです。お願いします。 import java.net.*; import java.io.*; public class client{ static final int BUFSIZE = 1792; public static void main(String[] args){ try{ String server = args[0]; //接続先のIPアドレス File file1 = new File(args[1]); //入力ファイル(HTTPリクエスト) FileReader filereader = new FileReader(file1); BufferedReader br = new BufferedReader(filereader); int serverport = Integer.parseInt(args[2]); //ポート番号 File file2 = new File(args[3]); //サーバからの応答をファイルに書き込む用 FileWriter filewriter = new FileWriter(file2); BufferedWriter bw = new BufferedWriter(filewriter); byte[] bytebuffer = new byte[BUFSIZE]; String str; while((str = br.readLine()) != null){ //入力ファイルの内容を1行ずつ読み込む bytebuffer = str.getBytes(); //入力ファイルの文字列をバイトに変換 } Socket socket = new Socket(server,serverport); //ソケットの生成 System.out.println("Connected to server...sending echo string"); InputStream in = socket.getInputStream(); //入出力ストリームの取得 OutputStream out = socket.getOutputStream(); out.write(bytebuffer); //文字列を送信 int receive; while((receive = in.read(bytebuffer))!=-1){ bw.write(new String(bytebuffer)); //サーバからの応答をファイルに出力 } bw.close(); socket.close(); }catch(IOException e){ } } }

  • c# ネットワークプログラム

    c#でネットワークプログラムを作る際、 SocketクラスとTcpListener・TcpClientクラスのどちらで 作るのが良いのでしょうか。 やりたいことは、サーバーとクライアントを接続して送受信させるだけです。

  • 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)接続してデータを送っても、向こうからデータが返ってこなければずっと待機したままです。たとえばミリセカンドで切ることはできないのでしょうか。 もしくは指定のミリセカンド経過後強制的にエラー処理に飛ばす等はできないのでしょうか。 通信処理をやるのが初めてで定石がよくわからず、あれこれ試している状態です。 処理についてご存じの方、ご指南いただけたらと思います。参考になるサイトや検索キーワードだけでも教えていただけたら嬉しいです。 よろしくお願いします。

  • ラズパイで1秒間隔で文字を送って、PC側で表示

    ラズパイのpythonを使って、windowsPCにVisual Studio 2013で作った簡易のtcpサーバーに接続して、1秒ぐらいの感覚で適当な文字データを送信して、サーバー側に表示するようにしたいと思っています。 しかし、サーバー側で表示する際に $ sudo python tcp_client1.py これで動かしているクライアントの起動を停止しないとサーバー側のテキストを表示するボックスに文字が表示されない現象が出ています。 いろいろと調べてみたところ、サーバー側の while(client.Connected) { receive = STR.ReadLine(); this.textBox2.Invoke(new MethodInvoker(delegate () { textBox2.AppendText("You : " + receive + "\n"); })); receive = ""; } ラズパイ側で起動しているクライアントプログラムの $ sudo python tcp_client1.py これが起動している最中は receive = STR.ReadLine(); このコード部分でずっとペンディング状態のようで、$ sudo python tcp_client1.pyを強制終了後に次の行の this.textBox2.Invoke(new MethodInvoker(delegate () { textBox2.AppendText("You : " + receive + "\n"); })); こちらに進むようで、このタイミングでテキストがボックスに表示されるような感じになります。 クラインアント側のコードは from __future__ import print_function import socket import time from contextlib import closing def main(): host = '192.168.11.14' port = 9000 bufsize = 4096 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) with closing(sock): sock.connect((host, port)) while 1: sock.send(b'Hello world') time.sleep(1.0) #print(sock.recv(bufsize)) #return if __name__ == '__main__': main() このような感じです。 1秒間隔で適当なテキスト文字”Hello world”を送信しているのですが、それを送信したらそれごとにサーバー側のテキストボックスに表示するようにするにはどうしたら良いのかご教示いただきますよう、よろしくお願いします。

  • Javaのネットワークに関して

    一つのサーバから複数のクライアントにメッセージを送るようにしなさい。いくつのクライアントと接続するか は入力により動的に決めるようにすること。複数のクライアントとの通信にはそのソケットを配列やコンテナを使って実装すればよい。サ ーバを「No23ex04Server」としクライアントを「No23ex04Client」とすること。 とあります。 以下のコードでクライアント側のプログラムは一切変えなくてよいそうなので、サーバー側のプログラムを以下のようにしたのですが、acceptが呼ばれている時点で、ループが止まってしまうので、入力待機状態になりません。スレッドを使わなくてもできるそうなのですが、私にはさっぱりです。 public class No23ex04Client { /** * @param args */ public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ String cIpAddress = null; String hostName = null; String sIpAddress = null; int portNo = 65535; try { cIpAddress = InetAddress.getLocalHost().getHostAddress(); hostName = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { } System.out.println("Client IP Address : " + cIpAddress); System.out.println("Host Name : " + hostName); Scanner scn = new Scanner(System.in); System.out.print("Server IP Address? : "); sIpAddress = scn.next(); System.out.print("Server Port Number? : "); portNo = scn.nextInt(); System.out.println("■Start■"); try { Socket sc = new Socket(sIpAddress, portNo); BufferedReader br = new BufferedReader(new InputStreamReader(sc.getInputStream())); while (true) { System.out.print("From Server Message : "); String fromServerMessage = br.readLine(); System.out.println(fromServerMessage); if (fromServerMessage.contains("さようなら")) break; } sc.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println("■Shutdown■"); } } public class No23ex04Server { /** * @param args */ public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ String ipAddress = null; String hostName = null; int portNo = 65535; try { ipAddress = InetAddress.getLocalHost().getHostAddress(); hostName = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e){ } System.out.println("IP Address : " + ipAddress); System.out.println("Host Name : " + hostName); Scanner scn = new Scanner(System.in); System.out.print("Port Number? : "); portNo = scn.nextInt(); System.out.print("Socket Number? : "); int num = scn.nextInt(); System.out.println("■Start■"); try { ServerSocket ssc = new ServerSocket(portNo); System.out.println("Serverが起動(Port Number : " + ssc.getLocalPort() + ")"); Socket[] sc = new Socket[num]; BufferedWriter[] bw = new BufferedWriter[num]; for (int i = 0; i < num; i++) { sc[i] = ssc.accept(); System.out.println("接続" + i + " : " + sc[i].getRemoteSocketAddress()); bw[i] = new BufferedWriter(new OutputStreamWriter(sc[i].getOutputStream())); } while (true) { System.out.print("To Client Message : "); String toClientMessage = scn.next(); for (BufferedWriter b : bw) { b.write(toClientMessage); b.newLine(); b.flush(); } if (toClientMessage.contains("さようなら")) break; } for (Socket s : sc) s.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println("■Shutdown■"); } }

    • ベストアンサー
    • Java
  • ソケットでのデータ送受信について教えてください

    はじめまして。 Perlでのソケット通信プログラムで質問があります。 現在ソケットで通信を行うテストプログラムを作っているのですが、 クライアントからサーバへの片方向送信は出来るのですが、 クライアントからデータ受信後、サーバからクライアントへ応答を 返す処理が上手くいきません。 私としては、クライアントとサーバの処理を逆にすればよいだけかな と思っているのですが認識違いでしょうか? 宜しくお願いします。 環境 OS:Linux 言語:Perl5.8 ■上手くいく場合(かなり省略します。ポイントだけ) サーバ側 $client=accept(C_SOCKET, P_SOCKET); while(<C_SOCKET>){ printf("%s",$_); #受信データ } クライアント側 socket (SOCKET, PF_INET, SOCK_STREAM, 0); connect(SOCKET, pack_sockaddr_in(9000,$ipaddr_bin)); print SOCKET "Test Data!!\n"; →サーバ側端末にTest Data!!と表示 ■送受信しようとしてダメなもの サーバ側 $client=accept(C_SOCKET, P_SOCKET); while(<C_SOCKET>){ printf("%s",$_); #受信データ } print C_SOCKET "Return Data!!\n"; クライアント側 socket (SOCKET, PF_INET, SOCK_STREAM, 0); connect(SOCKET, pack_sockaddr_in(9000,$ipaddr_bin)); print SOCKET "Test Data!!\n"; while(<SOCKET>){ printf("%s",$_); #応答データ } →サーバ側にはTest Data!!すら表示されない。  もちろんクライアント側にも。

    • ベストアンサー
    • Perl
  • UDPプログラム、データの送受信

    javaを使って通信の勉強をしています。 UDPを用いた通信のプログラムを作成しています。 送信側では、次のようにして送信したいバイト数を分割して送信しています。 BUF_MAX = 40960; DatagramSocket socket = new DatagramSocket(); // data分のバイトデータを分割して送信する。 int part = 5242880 / BUF_MAX; // 分割して送信する回数 send_start = System.nanoTime(); for(int i = 0;i < part;i++){   byte[] buf = new byte[BUF_MAX];   buf[0] = (byte)i;   DatagramPacket sendPacket = new DatagramPacket(buf,BUF_MAX,serverAddress,servPort);   total += BUF_MAX;   // 指定したバイト数を送信する。   try{     socket.send(sendPacket);   }catch(IOException e){     System.out.println(e);   } } System.out.println(total); このようにしています。 こうする理由は、5242880バイトのデータを128回に分割して送信して、 受信側で受信したパケットの最初の文字を見て、何個目のパケットが届いていないかを確認するためです。 受信側でこれらのデータを受信する方法を考えているのですが、どうすればよいか分かりません。 receive(packet)で受信するのは知っています。 送信された複数のデータを受信するのに、 for(int i = 0;i < 128; i++){  receive(packet); } というようにするのでしょうか?このようにすると、 このループを抜けることができません。それは、パケットが通信途中で紛失するため、128回受信しないからだとおもいます。 受信しなくなったらループを抜けるというようにすればよいとおもいますが、その方法が分かりません。 どなたかアドバイスをいただけないでしょうか?お願いします。

    • ベストアンサー
    • Java
  • streamで送信されたArrayListを変換したい

    以前ネットワークプログラミングについて質問したものです。 現在もjavaでソケットを使ったネットワークプログラミングを行っています。 現在、クライアントからサーバーに数値を送ってサーバーのArrayListのPOINTに格納しています。 そして、そのPOINTをstreamをつかってクライアントに送ってそのリストをクライアント側のArrayListに格納し、数字を出力しようと思っています。 しかし受け取ったPOINTをクライアント側のArrayListに格納しようとしても型が違う(stringだから)ので、うまく変換したいのですがうまくいきません。 送られてきたものをうまく型変換しクライアントのArrayListに格納する、また送信時にうまくArrayListを送信しクライアントで受信する方法はないでしょうか? サーバー PrintWriter out = new PrintWriter(((Socket) e.nextElement()).getOutputStream()); out.println(POINT); クライアント BufferedReader in; buff = in.readLine(); StringTokenizer st = new StringTokenizer(line); String cmd = st.nextToken(); CLPOINT = cmd; このような形で送信しています。 よい方法があればよろしくお願いします。

    • ベストアンサー
    • Java
  • byte配列の途中から2個ずつintに移すには?

    byte配列の途中から2個ずつintに移すには? Byte[] recvData={02:03:04:05:06:01:00:02:00:FF:FF:05} int nCount; =3;//データn個ください。 List<int> ValueList = new List<int>();//格納用 for (int i = 0; i < nCount; i++) {   //[0]~[4]までヘッダ+サブヘッダ。データは[5]から2byteずつ ValueList.Add(recvData[5 + i * 2] | (recvData[6 + i * 2] << 3)); }; という感じで、溜まったbyte配列の受信データから 0001、0002、65535とデータ部分を2byteずつ取り出したいのですが もうちょっとC#なら簡潔な書き方ってあるのでしょうか?

専門家に質問してみよう