• 締切済み

UDPサーバのスレッド化

JavaでUDPのサーバを作っているのですが、スレッド化ができません。] 以下の二つがキーワードだと思うのですが、どうかいていけばいいのかわかりません。お分かりになる方ご教授お願いいたします。 public class c_udp_server extends public void run() //サーバソース import java.io.*; import java.net.*; public class c_udp_server { public static void main(String args[]){ int port = 8000; BufferedInputStream biStream; InetAddress clientAddress; int clientPort; byte buf[]= new byte[160*120*3]; DatagramPacket sendPacket = new DatagramPacket(buf,buf.length); byte req[] = new byte[32]; DatagramPacket receivePacket = new DatagramPacket(req,req.length); try { DatagramSocket socket = new DatagramSocket(port); System.out.println("Running..."); while(true){ socket.receive(receivePacket); clientAddress = receivePacket.getAddress(); clientPort = receivePacket.getPort(); socket.send(receivePacket); sendPacket.setAddress(clientAddress); sendPacket.setPort(clientPort); sendPacket.setLength(160*120*3); biStream = new BufferedInputStream(new FileInputStream(s.raw)); for(;;){ biStream.read(buf,0,160*120*3); socket.send(sendPacket); if(buf[0] < 0)break; } biStream.close(); } } catch(Exception e){ System.out.println("Exception :" + e); } } } 環境 Windows XP Pro java version "1.5.0_10"

noname#106424
noname#106424
  • Java
  • 回答数3
  • ありがとう数7

みんなの回答

  • ngsvx
  • ベストアンサー率49% (157/315)
回答No.3

確認したわけではありませんが。。。 c_udp_serverSocket のコンストラクタでstart()メソッドを起動していますが、これが問題の気がします。 それから、全部見ていませんが、 サーバーはrecieveメソッドを抜けたらすぐにスレッドを生成し、 セッションの設定などはスレッドに任せてしまったほうが、 サーバーが開放される時間が早くなりますし、ソースコードの 可読性もあがると思います。 枠組みはこんな感じ(概略イメージ)。 while(){ socket.receive(receivePacket); thread = new XXXThraed(socket, sndPkt, rcvPkt); thread.start(); }

noname#106424
質問者

お礼

ご回答ありがとうございます!! ngsvxさんの意見を参考に頑張ってみます。 また何か分かりましたら、ご教授よろしくお願いいたします。

noname#106424
質問者

補足

TCPの感じと一緒のように考えればいいのでしょうか?以下のソースはスレッド化してあるTCPのサーバアです。枠組みの所と似ているので、このソースが参考になるのでしょうか!? import java.io.*; import java.net.*; import java.util.*;//連想配列を使用するために必要 public class thread_server extends Thread{//Threadクラスの継承 private Socket s; //ソケットの変数 static int count = 0; //同時接続数の初期化 //インスタンスでコンストラクタの設定 public thread_server(Socket s){ this.s = s; } //接続待ちまでの処理 public static void main(String[] args) { try{ InetAddress ipaddr = null; //アドレスの初期化 int port = 8000; //ポートの指定 ServerSocket ss = new ServerSocket(port);//ポート番号を指定してサーバソケットの作成 HashMap seMap = new HashMap();//クライアントごとの接続数のための連想配列 System.out.println("Running...\n"); while (true){ Socket s = ss.accept(); //クライアントからの接続待ち InetAddress addr = s.getInetAddress(); //ソケットの接続先のアドレスを返す String ad = addr.getHostName(); //ホスト名の保持 Integer value; count++; //同時接続の加算カウンタ System.out.println("現在接続中のクライアント数:" + count +"\n"); //連想配列にホスト名はあるかのチェック if (!seMap.containsKey(ad)) { seMap.put(ad, new Integer(1));//ないなら初期値に1 } //あるのならそれぞれのホストごとにカウント else { value = (Integer) seMap.get(ad); value = new Integer(value.intValue()+1); seMap.put(ad, value); } System.out.println("クライアント情報"); System.out.println("ホスト名:"+ ad); System.out.println("IPアドレス:"+ addr.getHostAddress()); System.out.println("ポート番号:"+ s.getPort()); System.out.println("接続回数:"+ seMap.get(ad)+"\n");    //sを初期値としたインスタンスを作成し //start()メソッドを呼び出してrun()メソッドを実行 new thread_server(s).start(); } } catch(Exception e){ System.err.println("Exception :" + e); } } //スレッドごとに実行する処理 public void run(){ try{ byte buf[] = new byte[160*120];//1フレームの配列 BufferedInputStream biStream; //spring.rawの中身をバッファの中に格納する biStream = new BufferedInputStream(new FileInputStream("spring.raw")); //バッファの中身をソケットに受け渡す DataOutputStream dos = new DataOutputStream(s.getOutputStream()); for(;;){ biStream.read(buf,0,160*120);//フレームとして読み込む dos.write(buf,0,160*120);//フレームとして書き込む if(buf[0] < 0)break;//フレームの最初の左端が0未満の時、終了 } count--; //同時接続の減算カウンタ //接続がない時と全ての接続が終了した時の表示 if(count==0){ System.out.println("現在接続中のクライアントはありません"+"\n"); } s.close(); } catch(Exception e){ System.err.println("Exception :" + e); } } }

  • PED02744
  • ベストアンサー率40% (157/390)
回答No.2

あなたのソースの中に、Thread クラスも Runnableインタフェースも 存在しないのですが、マルチスレッドアプリの仕組みはご存知でしょうか? [Java マルチスレッド プログラム]あたりをキーワードにして、 勉強されるほうがよろしいでしょう。 http://msugai.fc2web.com/java/thread/create.html このURLを参考にしていただいてもよろしいかと思います。

noname#106424
質問者

お礼

ご回答ありがとうございます!! 色々なサイトを拝見して継承などをしてみました。 コンパイルはとおったのですが、クライアントでアクセスすると動画の表示が始まりません。何か文法がおかしいのでしょうか? やりたいことはクライアントからアクセスがあった場合、クライアントごとに動画を配信したいのです。

noname#106424
質問者

補足

<pre><code> import java.io.*; import java.net.*; import java.util.*; public class c_udp_server2 { public static void main(String args[]){ int port = 8000; //ポート番号8000指定 InetAddress clientAddress;//クライアントのIPアドレス BufferedInputStream biStream; int clientPort; //クライアントのポート番号 //送信用のDatagramPacket byte buf[]= new byte[160*120*3]; DatagramPacket sendPacket = new DatagramPacket(buf,buf.length); //受信用のDatagramPacket byte req[] = new byte[32]; DatagramPacket receivePacket = new DatagramPacket(req,req.length); try { //指定したポートでソケットの作成 DatagramSocket socket = new DatagramSocket(port); System.out.println("Running..."); while(true){ socket.receive(receivePacket); clientAddress = receivePacket.getAddress(); clientPort = receivePacket.getPort(); socket.send(receivePacket); sendPacket.setAddress(clientAddress); sendPacket.setPort(clientPort); sendPacket.setLength(160*120*3); new c_udp_serverSocket(socket, sendPacket, receivePacket); } } catch(Exception e){ System.out.println("Exception :" + e); } } } class c_udp_serverSocket extends Thread{ BufferedInputStream biStream; DatagramSocket socket2; byte buf2[] = new byte[160*120*3]; DatagramPacket sendPacket2 = new DatagramPacket(buf2, buf2.length); byte req2[] = new byte[32]; DatagramPacket receivePacket2 = new DatagramPacket(req2, req2.length); c_udp_serverSocket(DatagramSocket socket, DatagramPacket sendPacket, DatagramPacket receivePacket) { socket2 = socket; sendPacket2 = sendPacket; receivePacket2 = receivePacket; try { biStream = new BufferedInputStream(new FileInputStream("file.raw")); } catch (Exception e) { System.err.println("Exception : " + e); } this.start(); } public void run() { try { for(;;){ biStream.read(buf2,0,160*120*3); socket2.send(sendPacket2); if(buf2[0] < 0)break; socket2.receive(receivePacket2); } biStream.close(); socket2.close(); } catch(Exception e){ System.out.println("Exception :" + e); } } } </code></pre>

  • ngsvx
  • ベストアンサー率49% (157/315)
回答No.1

サーバーでスレッドを使う以前に、単純なスレッドの使い方は知っているのですか?

noname#106424
質問者

お礼

ご回答ありがとうございます!! 上記にスレッド化(できているかわかりませんが)させたソースを添付しましたので、文法とうおかしな点があればご教授よろしくお願いいたします。

noname#106424
質問者

補足

詳しくはわかりませんが、サイトや書籍をみながら勉強しています。

関連するQ&A

  • javaのudp通信について

    javaのudp通信を使用して簡単なチャットプログラムを作っています。サーバーなどは使用しないものです。 送信、受信それぞれのプログラムはできました。送信は送信を繰り返し、受信も受信を繰り返すものです。それをひとつにしたいと考えています。 送信プログラムの詳細はhttp://oshiete1.goo.ne.jp/qa3743572.htmlです。 受信プログラムは下記です。 ご指導お願いします。 ******************************** import java.net.*; public class reciverTest { DatagramPacket packet1; private DatagramSocket socket1; private int port = 19800; public reciverTest() throws Exception { this.socket1 = new DatagramSocket(this.port); } public String receive() throws Exception { byte buffer[] = new byte[256]; int i; packet1 = new DatagramPacket(buffer, buffer.length); this.socket1.receive(packet1); // blocking for (i = 0; i < buffer.length; i++) { if (buffer[i] == '\0') { break; } } String msg = new String(packet1.getData(), 0, i); return msg; } public void close() throws Exception { socket1.close(); } public static void main(String[] args) { reciverTest receiver1; System.out.println("Waiting ..."); try { receiver1 = new reciverTest(); while(true) { String msg = receiver1.receive(); System.out.println("受信したデータ⇒『" + msg +"』を受信しました。"); receiver1.close(); } } catch (Exception ex) { System.err.println("Error: " + ex.getMessage()); } } }

    • ベストアンサー
    • Java
  • UDP通信(SNMP)したいが、うまく動かない。

    下記URLの質問の続きのような質問なのですが…。 SNMPで応答を得ようと、下記のようにコードを書いてみたのですが、うまくいきません。 足りないところ、間違っているところ、こうしたらいいんじゃない?等、簡単なことでも結構です。 ご教授いただけたらと思います。 よろしくお願いします。 http://oshiete1.goo.ne.jp/qa4934857.html //ここからコード public class SNMP_UDPReceive2 { public static void main(String[] arg){ System.out.println("hajimata!"); try{ byte buf[] = "Get".getBytes(); //ソケットを作成 DatagramSocket soc = new DatagramSocket(); //パケットを作成(""の中身は例です。) DatagramPacket packet = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.0.1"),161); //送信 soc.send(packet); //受信処理 byte buf_re[] = new byte[512]; DatagramPacket packet_re = new DatagramPacket(buf,buf.length); soc.receive(packet_re); //受信したデータを取得 String data = new String(packet_re.getData(),0,packet_re.getLength()); System.out.println("\"" + data + "\"を受信しました"); }catch(Exception e){ e.printStackTrace(); } } }

    • ベストアンサー
    • Java
  • 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
  • javaのUDP受信プログラムについて

    UDPで数値データを受信してある処理をしようと考えております。 そこで↓のページで公開されている受信プログラムを使用してデータを受信しました。 http://news.mynavi.jp/column/java/052/index.html import java.net.*; public class UDPServer { public static void main(String[] argv) throws Exception { // 5100番ポートを監視するUDPソケットを生成 DatagramSocket receiveSocket = new DatagramSocket(5100); // 受け付けるデータバッファとUDPパケットを作成 byte receiveBuffer[] = new byte[1024]; DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length); while (true) { // UDPパケットを受信 receiveSocket.receive(receivePacket); // 受信したデータを標準出力へ出力 System.out.println (new String(receivePacket.getData(), 0, receivePacket.getLength())); } } } 別のプログラムから「50」という数値を送信し、上記のプログラムで受信すると、勝手にASCIIコードに変換されてしまっているようで、ASCIIコードの10進数の50にあたる「2」が出力されてしまいます。 これをASCIIコードに変換せずに、表示させる方法を教えて下さい。 もしくは、受信データをバイナリで表示する方法があれば、そちらも教えていただけるとありがたいです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • javaによるファイル送信のプログラム

    ユニキャスト通信のおけるプログラミングで、1のプログラムを2のプログラムを使ってファイル送信ができるようにしたいのですがうまくいきません。私のjavaの知識が授業についていかなくて図書館でいろいろと本を探したのですが見つかりませんでした。誰か教えていただけませんか? /*1*/ import java.net.*; import java.io.*; public class udpechoServer{ static final int echo_PORT = 7; //エコーポート番号 static final int BUFSIZE = 1024; //バッファサイズ public static void main(String[] args) throws IOException{ int port = echo_PORT; //ポート番号 int cliport; //クライアントポート番号 int len; //データ長 int i; //キーインバッファクリアインデックス DatagramSocket sock = null; //データグラムソケット宣言,初期化 byte[] buf = new byte[BUFSIZE]; byte[] wbuf = new byte[BUFSIZE]; String recvdata; //受信データ try{ sock = new DatagramSocket(port); DatagramPacket recvpacket = new DatagramPacket(buf,BUFSIZE); DatagramPacket sendpacket = new DatagramPacket(buf,BUFSIZE); System.out.println("Connected to echo server"); while(true){ sock.receive(recvpacket); //データ受信 recvdata = new String(recvpacket.getData(),0,recvpacket.getLength()); recvdata = recvdata.trim(); //トリミング(CRLF) wbuf = recvdata.getBytes(); //文字列→バイト配列変換 i = 0; len = wbuf.length; buf = new byte[BUFSIZE]; while(wbuf[i] != 0x0d){ //途中のCR検出 buf[i] = wbuf[i]; //データコピー i++; if(i >=len){ break; } } recvdata = new String(buf,0,i); //バイト配列→文字列変換 System.out.println(recvdata); //画面出力 InetAddress ipadr = recvpacket.getAddress(); cliport = recvpacket.getPort(); buf = recvdata.getBytes(); len = buf.length; sendpacket = new DatagramPacket(buf,len,ipadr,cliport); sock.send(sendpacket); //データ送信 recvpacket.setLength(BUFSIZE); //データグラムパケット長リセット } }catch(SocketException e){ e.printStackTrace(); } } } /*2 */ import java.io.*; class FileCopy { public static void main(String argv[]){ try{ InputStream in = new FileInputStream(argv[0]); //入力ファイルを開く //BufferedInputStreamオブジェクトの生成 BufferedInputStream bin = new BufferedInputStream(in); OutputStream out = new FileOutputStream(argv[1]); //出力ファイルを開く //BufferedOutputStreamオブジェクトの生成 BufferedOutputStream bout = new BufferedOutputStream(out); byte buf[] = new byte[1024]; int c; //読み込みデータがなくなるまで読み込み while((c = bin.read(buf, 0, buf.length)) != -1){ bout.write(buf, 0, c); //データの書き込み処理 } System.out.println("\""+argv[0]+"\" was converted into \""+argv[1]+"\""); bin.close(); //入力ファイルを閉じる bout.close(); //出力ファイルを閉じる }catch(Exception e){} } }

    • ベストアンサー
    • Java
  • javaの課題プログラムでどうしてもわかりません。

    以下(senderTest)のプログラムを適切に繰り返すように書き換えたいのですが、どうしてもうまくいきません。while文で自分なりに繰り返した結果は同じ文字を送り続けるというものになってしまいました。 本来は送信して、待機状態になりまた新たに文字を入力したら送信、また待機というようにしたいのですがどうしたらよいでしょうか? どうかよろしくおねがいします。 ******************************** senderTest import java.io.*; import java.net.*; public class senderTest { private InetAddress address; private int port = 13400; private DatagramSocket socket; public senderTest() throws Exception { this.address = InetAddress.getByName("192.168.0.16"); this.socket = new DatagramSocket(); } public void send(String s) throws Exception { byte buffer[]; buffer = s.getBytes("Shift_JIS"); DatagramPacket packet = new DatagramPacket(buffer, buffer.length, this.address, this.port); this.socket.send(packet); } public static void main(String[] args)throws IOException { senderTest sender1; System.out.println("↓送信する文字を入力してください↓"); String name = ("健児>"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String msg = name +br.readLine(); try { sender1 = new senderTest(); sender1.send(msg); System.out.println("『" + msg + "』を送信しました。"); } catch (Exception ex) { System.err.println("Error: " + ex.getMessage()); } } } ********************************

    • ベストアンサー
    • Java
  • 特定のIPアドレスとUDP接続したい

    表題のとおり、あるサーバからUDPでデータを受け取りたいのですが、いまいち方法が解らないで困っております。 具体的にはネット対戦のサーバからUDPで吐き出されている プレイヤーの戦績を受けてデータベースに入れていくアプリケーションを開発しようと思っております。 ゲームサーバは外部です、 ソースコードにはどう記述したら良いでしょうか? public static int port = 1716; public static String ip = "213.228.238.188"; DatagramSocket ds = new DatagramSocket(port); ココまでは良いのですが、この後が八方塞です。 基本的なことかもしれませんが何卒宜しくお願いいたします。

  • TCPプログラミング

    以下のプログラムをコンパイルして実行したら Exception in thread "main" java.lang.IllegalArgumentException: Paraneter(s):<Server> <Word> [<Port>] at TCPEchoClient.main(TCPEchoClient.java:9) というメッセージが表示されました。 このメッセージの意味が全く分かりません。 分かる方がいらっしゃいましたら教えてください。 お願いします。 本来なら Received:****(←****は自分が指定した文字列) となるはずなんですが… このプログラムはTCPを使ってエコーサーバと通信するクライアントです。 import java.net.*; import java.io.*; public class TCPEchoClient{ 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]; 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(); } }

  • javaでWebサーバー

    今学校の課題でjavaで簡単なWebサーバーを作っています トップディレクトリのdocrootフォルダ下のファイルにアクセスできるようにしました 内容は以下の様です import java.io.File; import java.net.Socket; import java.net.ServerSocket; /** * 簡単なWebサーバ. */ public class HTTPServer { /** * サーバソケット */ private ServerSocket server; /** * Webサイトのトップディレクトリ */ private String docRoot; /** * サーバーソケットを作成する。 * @param port このサーバが受け付けるポート番号 * @param docRoot Webサイトのトップディレクトリ */ private HTTPServer(int port, String docRoot) throws java.io.IOException { server = new ServerSocket(port); this.docRoot = docRoot; } /** * サーバのサービスを行うメソッド. */ private void doService() { System.out.println("Starting Server Service!!"); while (true) { try { Socket client = server.accept(); ClientHandler clientHandler = new ClientHandler(client, docRoot); clientHandler.doService(); } catch (Exception e) { // スタックトレースの表示 e.printStackTrace(); } } } /** * サーバ起動のための主メソッド. * 起動方法:トップディレクトリにて * <pre> * java -cp lib pro3.HTTPServer ポート番号 * </pre> */ public static void main(String[] args) { if (args.length != 1) { System.err.println("usage: java HTTPServer port_number"); System.exit(1); } int port = -1; try { port = Integer.parseInt(args[0]); // 文字列を整数へ変換 } catch (Exception e) { System.err.println("Invalid port number."); System.exit(1); } // Webサイトのトップディレクトリ(カレントディレクトリのdocroot)を求める. String docRoot = System.getProperty("user.dir") + File.separator + "docroot"; try { HTTPServer server = new HTTPServer(port, docRoot); server.doService(); } catch (Exception e) { // スタックトレースの表示 e.printStackTrace(); } } } doServiceで指定したファイルを読んで返したりしています ここで質問なのですが このサーバーを動かしている時に http://localhost:ポート/index.html でアクセスするたびにindex.htmlをきちんと出力してくれます しかしソースを読む限りだとループしているようには思えないのですが どのように繰り返しを行っているのですか?

    • ベストアンサー
    • Java
  • TCPプログラミング

    次のコードを入力したのですが、コンパイルできません。 エラーについても良く分かりません。 import java.net.*; import java.io.*; public class TCPEchoClient{ 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]; 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(); } } これについて、 if(bytesRcvd = in.read(byteBuffer, totalBytesRcvd, byteBuffer.length - totalBytesRcvd) == -1) この行にエラーがあるらしいです。 どう解決していいのか分かりません。 どなたか説明してもらえませんか。

    • ベストアンサー
    • Java