UDP 接続オブジェクトの原理分析と使用例

UDP 接続オブジェクトの原理分析と使用例

以前、UDP を使い始めるために簡単な UDP サーバーとクライアントの例を作成しましたが、実際に使用してみると問題が発生しました。

前回使用したときも、接続オブジェクト DatagramSocket を static として記述し、クラスの初期化時に使用していました。しかし、システム内の多くの場所で使用されています。このクラスのオブジェクトを作成し続ける必要がありますか?

これを実行することは可能ですが、メモリ オーバーフローという結果を招く可能性があります。

UDP はステートレスです。DatagramSocket は、特定のアドレスのポートを指すために、毎回作成する必要はなく、一度作成するだけで済みます。

UDP はステートレスなので、DatagramSocket オブジェクトを作成すると、ネットワークを指すオブジェクトのみが作成されます。これは、特定の方向を向いた大きなスピーカーを設置しても、その方向で聞いている人がいるかどうかはわからないのと同じです。

サーバーが稼働していなくても、接続オブジェクトを作成してこのアドレスにデータを送信しても問題はありません。拡声器で特定の方向に向かって叫んでも、誰も聞いてくれなければ意味がありません。ただし、必要なときに応答が受信されない場合は、タイムアウト後にエラーが報告されます。

パッケージ udp; 
 
java.net.* をインポートします。 
 
/** 
 * @Description UDP クライアント プログラム。サーバーにデータを送信し、サーバーの応答情報を受信するために使用されます。* @author cuisuqiang 
 * @バージョン 1.0 
 * @since <a href="mailto:[email protected]" rel="external nofollow" >[email protected]</a> 
 */ 
パブリッククラス UdpClientSocket { 
  /** 
   * 接続オブジェクト */ 
  プライベート静的 DatagramSocket ds = null; 
  /** 
   * アドレスオブジェクト */ 
  プライベート静的SocketAddressアドレス = null; 
   
  /** 
   * クライアントのパケット送信方法と応答情報の受信方法をテストします*/ 
  パブリック静的void main(String[] args)は例外をスローします{ 
    初期化(); 
    while(true){ 
      UdpClientSocket.send(address,"こんにちは、親愛なる!".getBytes()); 
      UdpClientSocket を受信します。 
      試す { 
        スレッドをスリープ状態にします(3 * 1000); 
      } キャッチ (例外 e) { 
        e.printStackTrace(); 
      } 
    } 
  } 
   
  /** 
   * 接続とアドレスを初期化します */ 
  パブリック静的void init(){ 
    試す { 
      ds = new DatagramSocket(8899); // クライアントとしてローカルポートにバインド ds.setSoTimeout(2 * 1000); 
      アドレス = 新しい InetSocketAddress("127.0.0.1",3344); 
    } キャッチ (例外 e) { 
      e.printStackTrace(); 
    } 
  } 
   
  /** 
   * 指定されたサーバーにデータ情報を送信します */ 
  パブリック静的void送信(SocketAddressアドレス、byte[]バイト){ 
    試す { 
      DatagramPacket dp = 新しい DatagramPacket(バイト、バイト長、アドレス); 
      ds.send(dp); 
    } キャッチ (例外 e) { 
      e.printStackTrace(); 
    } 
  } 
 
  /** 
   * 指定されたサーバーから送り返されたデータを受信します*/ 
  パブリック静的void受信(){ 
    試す { 
      byte[] buffer = 新しいbyte[1024]; 
      DatagramPacket dp = 新しい DatagramPacket(バッファ、バッファ長); 
      ds.receive(dp);    
      byte[]データ = new byte[dp.getLength()]; 
      System.arraycopy(dp.getData(), 0, データ, 0, dp.getLength());  
      System.out.println("サーバー応答データ: " + new String(data)); 
    } キャッチ (例外 e) { 
      e.printStackTrace(); 
    } 
  } 
}

コードを実行した結果は次のとおりです。

java.net.SocketTimeoutException: 受信がタイムアウトしました
java.net.PlainDatagramSocketImpl.receive0(ネイティブメソッド)
java.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:136) で
java.net.DatagramSocket.receive(DatagramSocket.java:712) で
udp.UdpClientSocket.receive(UdpClientSocket.java:69) で
udp.UdpClientSocket.main(UdpClientSocket.java:28) で

操作はタイムアウトしましたが、エラーはオブジェクトの作成とデータの送信によって発生したのではなく、データ受信時のタイムアウトによって発生しました。

このプログラムは実行し続けますので、サーバーを作成しましょう。

パッケージ udp;

java.net.DatagramPacket をインポートします。
java.net.DatagramSocket をインポートします。
java.net.InetSocketAddress をインポートします。
java.net.SocketAddress をインポートします。

/**
 * @UDP サービスクラスの説明 * @author cuisuqiang
 * @バージョン 1.0
 * @since [email protected]
 */
パブリッククラス UdpServerSocket {
	
	プライベート静的 DatagramSocket ds = null;
	プライベート静的SocketAddressアドレス = null;
	
	/**
	 * テスト方法 */
	パブリック静的void main(String[] args)は例外をスローします{
		初期化();
		System.out.println("---->サービスがリッスンを開始します!<----");
		(真)の間{
			UdpServerSocket.receive();
			UdpServerSocket.response(address,"こんにちは、食事はしましたか?");
		}		
	}
	
	パブリック静的void init(){
		試す {
			ds = 新しいデータグラムソケット(3344);
			ds.setSoTimeout(0);
			アドレス = 新しい InetSocketAddress("127.0.0.1",8899);
		} キャッチ (例外 e) {
			e.printStackTrace();
		}
	}

	/**
	 * データパケットを受信します。このメソッドはスレッドをブロックします */
	パブリック静的void受信() {
		試す {
			byte[] buffer = 新しいbyte[1024];
			DatagramPacket パケット = 新しい DatagramPacket(バッファ、バッファ長);
			ds.receive(パケット);
			文字列情報 = 新しい文字列(packet.getData(), 0, packet.getLength());
			System.out.println("情報を受信: " + info);
		} キャッチ (例外 e) {
			e.printStackTrace();
		}
	}

	/**
	 * 応答パケットを要求元に送信する */
	パブリック静的void応答(SocketAddressアドレス、文字列情報){
		試す {
			DatagramPacket dp = 新しい DatagramPacket(info.getBytes(), info.getBytes().length, address);
			dp.setData(info.getBytes());
			ds.send(dp);
		} キャッチ (例外 e) {
			e.printStackTrace();
		}		
	}
}

実行後、クライアントは正常にデータを送受信できるようになります。

実際に使用する場合は、システム スタートアップ項目を設定して、init 接続オブジェクトとアドレスを初期化し、使用時に例外をキャプチャします。

接続オブジェクトが毎回作成され、頻繁に使用される場合、通常、システムは数分以内にクラッシュします。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • UDP シンプル サーバー クライアント コード例
  • Python UDPプログラミングの詳細な説明
  • TCP/UDP プロトコルを使用した C# サンプル コード
  • UDP チャット プログラムに基づく Java ネットワークの例の分析
  • Java シミュレーション UDP 通信サンプル コード
  • PythonはUDPプログラム通信プロセス図を実装します
  • PythonはUDPプロトコルによるファイル転送を実装する
  • Java UDP 通信クライアントとサーバーの例の分析

<<:  JavaScript 配列重複排除ソリューション

>>:  2 つの MySQL ユーザー削除ステートメント (delete user と drop user) の違い

推薦する

Linux IO 多重化 epoll ネットワーク プログラミング

序文この章では、基本的な Linux 関数と epoll 呼び出しを使用して、Linux 上で実行で...

MySQLステートメントの記述と実行順序を理解するだけです

MySQL ステートメントの書き込み順序と実行順序には大きな違いがあります。書き順、mysql の一...

MySql インデックスを表示および最適化する方法

MySQL はハッシュ インデックスと Btree インデックスをサポートしています。 InnoDB...

MySQL テーブル分割後にスムーズにオンラインになる方法

目次テーブルの目的例えばテーブル分割戦略すでにオンラインになっている実行中のテーブルはどうすればよい...

Linux でファイルを削除するときに「操作は許可されていません」というプロンプトが表示される場合の対処方法

同僚からよく聞かれるのですが、ファイル/ディレクトリを削除すると「操作は許可されていません」というエ...

MySQLはテーブルデータを復元するためにfrmファイルとibdファイルを使用します

目次frm ファイルと ibd ファイルの紹介frm ファイル回復テーブル構造ibd ファイル回復テ...

CSSのtranslate(-50%,-50%)は水平および垂直の中央揃え効果を実現します。

translate(-50%,-50%) 属性:中央に配置するには、長さと幅の 50% だけ上と左...

Vueインスタンスで$refsを使用する際の注意点

開発の過程では、インスタンスの vm.$refs(this.$refs) を使用して、ref で登録...

MySQLインデックスの基本構文

インデックスはソートされたデータ構造です。 where 条件での検索や order by 条件での並...

HTML テーブル マークアップ チュートリアル (9): セル間隔属性 CELLSPACING

テーブルがコンパクトになりすぎないように、テーブル内のセル間に一定の距離を設定できます。基本的な構文...

Linux で環境変数 JAVA_HOME を変更/設定する方法について簡単に説明します。

1. 永久的な変更、すべてのユーザーに有効# vi /etc/プロファイル//キーボードの[Shi...

HTML コード例: ハイパーリンクの詳細な説明

ハイパーリンクは、Web サイト上のすべてのページがハイパーリンクで接続され、ページ間を移動できるた...

nginx を使用したプロキシ サーバーの設定

Nginx は、リバース プロキシ機能を使用して負荷分散を実装できるほか、フォワード プロキシ機能を...

Vueライフサイクルの詳細な説明

目次ライフサイクルを理解する理由ライフサイクルとはライフサイクルフック関数作成され、マウントされたフ...