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

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

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

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

1回答

3084閲覧

KotlinでUDP受信しない

HYDESA

総合スコア8

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2021/10/12 08:05

編集2021/10/28 08:18

いつもお世話になっています。
AndroidアプリでTCP/IPの通信をやりたく、現在勉強中ですが
まずはUDPからと始めたソースがうまく動いてくれません。

前提・実現したいこと

UDPで送受信をしたいが受信がされない。
UDPの送信は受信前に完了済み。

発生している問題・エラーメッセージ

受信待ちになっているかと思われるが、
うんともすんとも言わない。
(WiresharkやUDPツールでパケット受信は確認済)

該当のソースコード

画面は受信した内容を表示するTextViewが一つのみ

kotlin

1class ReceiveWindow : AppCompatActivity() { 2 override fun onCreate(savedInstanceState: Bundle?) { 3 super.onCreate(savedInstanceState) 4 setContentView(R.layout.activity_receive_window) 5 6 // 受信表示用TextViewを取得 7 val receiveView = findViewById<TextView>(R.id.textView) 8 9 // 受信処理開始 10 thread { 11 val msg = ByteArray(256) 12 val receiveSocket = DatagramSocket() 13 socket.connect(InetAddress.getByName("192.168.0.115"), 50000) 14 val packet = DatagramPacket(msg, msg.size) 15 Log.d("NetworkStatusExample", "Receive Start") // ログに表示 16 receiveSocket.receive(packet) 17 Log.d("NetworkStatusExample", "Receive Stop") // これはログに表示されていない 18 receiveView.text = msg.toString() 19 receiveSocket.close() 20 } 21 } 22}

試したこと

val receiveSocket = DatagramSocket(50000)とやると
ポート確認のsocket.portで -1 の値が表示されてしまうため
あえてsocket.connectを使用しています。

Try-catchでエラーが出ているかどうかを確認しましたが、
特にエラーは無し。

補足情報(FW/ツールのバージョンなど)

カスペルスキーが邪魔をしていたので、無効化。
FireWallにUDPポート50000の許可を登録。

送信側は別PCのPython3でsendと記述したパケットを送信。
受信確認はTCP/IPツールでUDP受信を確認。
(併せてWiresharkでも受信を確認済み)

イメージ説明

Android Studio: 2020.3.1 Patch2
Kotlin: 203-1.5.31-release-550-AS7717.8
AndroidManifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


申し訳ありませんが、どなたかご教示くださいませ。

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

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

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

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

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

y_waiwai

2021/10/12 10:32

ログ出力はどう出力されてるんでしょうか
jimbe

2021/10/12 11:13 編集

> 受信待ちになっているかと思われるが まず udpReceiveFunction の前後でログを出すのではなく、receiveSocket.receive(packet) の前後でログを出すべきではないでしょうか。
HYDESA

2021/10/28 08:01 編集

y_waiwaiさん、書き込みありがとうございます。 ログは下記の通りです。 Receive Start 以後うんともすんとも言いません。。。 10/13 11:10:09: Launching 'app' on Pixel 2 API 28. App restart successful without requiring a re-install. $ adb shell am start -n "com.example.packetplayer/com.example.packetplayer.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER Connected to process 5293 on device 'Pixel_2_API_28 [emulator-5554]'. Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page. W/le.packetplaye: Accessing hidden method Landroid/graphics/drawable/Drawable;->getOpticalInsets()Landroid/graphics/Insets; (light greylist, linking) Accessing hidden field Landroid/graphics/Insets;->left:I (light greylist, linking) Accessing hidden field Landroid/graphics/Insets;->right:I (light greylist, linking) Accessing hidden field Landroid/graphics/Insets;->top:I (light greylist, linking) W/le.packetplaye: Accessing hidden field Landroid/graphics/Insets;->bottom:I (light greylist, linking) W/le.packetplaye: Accessing hidden field Landroid/view/WindowInsets;->CONSUMED:Landroid/view/WindowInsets; (light greylist, reflection) W/le.packetplaye: Accessing hidden method Landroid/view/View;->getAccessibilityDelegate()Landroid/view/View$AccessibilityDelegate; (light greylist, linking) W/le.packetplaye: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (light greylist, reflection) W/le.packetplaye: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (light greylist, reflection) D/OpenGLRenderer: Skia GL Pipeline W/le.packetplaye: Accessing hidden method Landroid/graphics/Insets;->of(IIII)Landroid/graphics/Insets; (light greylist, linking) D/HostConnection: HostConnection::get() New Host Connection established 0xe3aac280, tid 5319 D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_YUV420_888_to_NV21 ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer ANDROID_EMU_sync_buffer_data GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_async_frame_commands ANDROID_EMU_gles_max_version_3_0 I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0 I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 0 I/OpenGLRenderer: Initialized EGL, version 1.4 D/OpenGLRenderer: Swap behavior 1 W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without... D/OpenGLRenderer: Swap behavior 0 D/eglCodecCommon: setVertexArrayObject: set vao to 0 (0) 0 0 D/EGL_emulation: eglCreateContext: 0xe3a854e0: maj 3 min 0 rcv 3 D/EGL_emulation: eglMakeCurrent: 0xe3a854e0: ver 3 0 (tinfo 0xe3a836a0) D/HostConnection: createUnique: call D/HostConnection: HostConnection::get() New Host Connection established 0xe3aac500, tid 5319 D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_YUV420_888_to_NV21 ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer ANDROID_EMU_sync_buffer_data GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_async_frame_commands ANDROID_EMU_gles_max_version_3_0 E/eglCodecCommon: GoldfishAddressSpaceHostMemoryAllocator: ioctl_ping failed for device_type=5, ret=-1 D/EGL_emulation: eglMakeCurrent: 0xe3a854e0: ver 3 0 (tinfo 0xe3a836a0) D/eglCodecCommon: setVertexArrayObject: set vao to 0 (0) 1 2 I/AssistStructure: Flattened final assist data: 3556 bytes, containing 1 windows, 12 views I/AssistStructure: Flattened final assist data: 3604 bytes, containing 1 windows, 12 views W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@8cbd079 D/EGL_emulation: eglMakeCurrent: 0xe3a854e0: ver 3 0 (tinfo 0xe3a836a0) D/EGL_emulation: eglMakeCurrent: 0xe3a854e0: ver 3 0 (tinfo 0xe3a836a0) D/EGL_emulation: eglMakeCurrent: 0xe3a854e0: ver 3 0 (tinfo 0xe3a836a0) D/NetworkStatusExample: Receive Start
HYDESA

2021/10/13 02:13

jimbeさん、書き込みありがとうございます。 確かに、その通りですね(汗。 上記ログは仰せの通りと致しました。 ありがとうございました。
HYDESA

2021/10/29 08:13

receiveコマンドの check Accept を調べていたところ、 ポート転送なるものを発見しました。 これをやらないと、エミュレーターに入ってこないのでしょうか? またどうやってやればよいのでしょうか。 今回で言うと 外部PCから開発PCへSend  192.168.0.115:50000 に向けて 開発PCは  192.168.0.115:50000 からポートホワンディングで   →10.0.2.15:54321:50000 で    socket.connect(InetAddress.getByName("10.0.2.2"), 54321) こういう事でしょうか?
HYDESA

2021/11/01 06:02 編集

jimbeさん、書き込みありがとうございます。 そうです、ここら辺の話かと思われます。 いろいろとやってはみていますが、一向に受信しません。 で、ログを見ていると画面遷移後に下記のワーニングを発見しましたが、 何か関係あるのでしょうか?   W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@fa07d53 ちなみにMainActivity.ktからこのウインドウに移る時は、 IPアドレスとポート番号を入力し、その値を遷移させ、 上記の処理を行っています。 なお、直接IPアドレスやポート番号を入力していたため(入力の手間を省く意味で) 上記ソースには記載していませんでした。 【遷移時の値セット】 ipAddress = intent.getStringExtra("hostName").toString() findViewById<TextView>(R.id.textViewR2).text = ipAddress // ポート番号 val exPortNum = intent.getStringExtra("portNum").toString() findViewById<TextView>(R.id.textViewR4).text = exPortNum // 文字列を数値に変換 //Constants.PORTNUM = exPortNum.toInt() portNum = exPortNum.toInt() val returnButton = findViewById<Button>(R.id.buttonR1) // 受信した文字列をviewに表示 val receiveView = findViewById<TextView>(R.id.textViewR5)
HYDESA

2021/11/01 08:45

たびたびすいません。 アドレスを 0.0.0.0 にしてやってみましたが、 ポートが空いているかどうか netstat で調べたところ、 開放されていないようです。 socket.connect(InetAddress.getByName("0.0.0.0"), 50000) UDP 0.0.0.0:17500 *:* UDP 0.0.0.0:49699 *:* UDP 0.0.0.0:52103 *:* UDP 0.0.0.0:57007 *:* UDP 0.0.0.0:57010 *:* redir でフォワードすると、 UDP 127.0.0.0: 50000 と表示されます。 本来なら 0.0.0.0 側に開けなければいけないのでは? と考えますが、いかがでしょうか。
jimbe

2021/11/01 10:40 編集

なんだかオオゴトになっているような気がしますが…。 ログに出たというワーニングは、何のものか分かりませんが…何となく問題無さそうな気がします。(根拠ありません。) もし実機と Wifi をお持ちであれば、アプリを実機にインストールし、 Wifi 経由で送信 PC から直接送信してみては如何でしょうか。 また、もしやエミュレータ等にいろいろ設定が溜って良く分からない状況になっているかもしれませんので、一旦リセットする意味でエミュレータを作り直してみる等は如何でしょうか。
jimbe

2021/11/01 18:11 編集

試しながら情報を探していたのですが、エミュレータのバグによるもの( https://issuetracker.google.com/issues/80149140 ) というのはありましたが、 wifi を off (エミュレータ起動オプションに -feature -Wifi を指定) しても変わりませんでした。 上に書いたように、実機に受信を入れ同一LAN内の PC から送信を試すとちゃんと届きます。 試しに、送信を 192.168.1.6:50000 と 192.168.1.6:500002 ( 192.168.1.6 はホストのLAN側アドレス) に行うようにし、エミュレータには redir add udp:50000:50000 と redir add udp:50001:50001 を行って、ホストPC では 50002 に受信したデータを localhost:50001 に送信するプログラム(自作リダイレクタ?) を動かしてみますと、 50000 は受信しませんでしたが 50001 は受信しました。 つまり redir によるリダイレクト指定は、localhost からの送信はリダイレクトしても、外からのはしていない(出来ていない)風です。
jimbe

2021/11/01 18:07

受信側の DatagramSocket はアドレスを指定しないで DatagramSocket(50000) 等とやっています
HYDESA

2021/11/03 06:08 編集

jimbeさん、ご教示ありがとうございます。 どうしたらよいか、完全に詰まってしまっているので、かなり焦ってます(汗。 >もし実機と Wifi をお持ちであれば、アプリを実機にインストールし、 Wifi 経由で送信 PC から直接 >送信してみては如何でしょうか。 >また、もしやエミュレータ等にいろいろ設定が溜って良く分からない状況になっているかもしれません >ので、一旦リセットする意味でエミュレータを作り直してみる等は如何でしょうか。 そうですね、実機は手元にありますので、ちょっとやってみますが 会社のWi-FiはMACアドレス制御していますので、砦が厳しいかもです。。。 あとエミュレーターのリセットの件ですが、早速やってみます。 もしこれで通信が出来るようになれば、無駄な作業をしなくて済みますので。 >試しに、送信を 192.168.1.6:50000 と 192.168.1.6:500002 ( 192.168.1.6 はホストのLAN側アド >レス) に行うようにし、エミュレータには redir add udp:50000:50000 と redir add >udp:50001:50001 を行って、ホストPC では 50002 に受信したデータを localhost:50001 に送信す >るプログラム(自作リダイレクタ?) を動かしてみますと、 50000 は受信しませんでしたが 50001 は受 >信しました。 >つまり redir によるリダイレクト指定は、localhost からの送信はリダイレクトしても、外からのはして >いない(出来ていない)風です。 検証くださったんですね、ありがとうございます。 redir だと 127.0.0.1:50000 というポートが開くので、外部からの受信には 対応できないと思っていましたが、やはりその通りになったという事ですね。 0.0.0.0:50000 が開けば問題ないのですが。。。 >受信側の DatagramSocket はアドレスを指定しないで DatagramSocket(50000) 等とやっています そうなんですね、ありがとうございます。 それではそれでやってみます。 いろいろと助かります。 早速やってみますね。 ありがとうございました。
HYDESA

2021/11/03 07:52 編集

エミュレーターの削除をやってみましたが、やっぱりうまくいきません。 (実機はWi-Fi担当が不在でまだ出来てません) ところで権限の設定等はありますでしょうか。 エミュレーター側のアプリ設定だと、権限はありませんと表示されています。 Manifestには下記が記載してあります。 <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> ネットワーク系は権限呼出ししなくてもよいとの記述は見つけたのですが。。。   注: Internet 権限と ACCESS_NETWORK_STATE 権限はどちらも標準の権限です。   つまり、インストール時に付与され、実行時にリクエストする必要はありません  https://developer.android.com/training/basics/network-ops/connecting?hl=ja
jimbe

2021/11/03 09:10

権限は INTERNET のみです。 今 TCP でも試しているのですが、 redir してもこちらも通りません。ですので UDP/TCP 問わずで検索していますが・・・どちらかが分かればもう一方も分かるかもしれませんね。 USB を LAN アダプタ的に使って通信出来たような気もするのですが、試そうとしたこともありませんので、android の設定で出来るのか USB 接続の LAN アダプタを付けての話だったかも分かりません。
jimbe

2021/11/04 11:23 編集

adb でのフォワーディングなら何か変えられるかと思いましたが、やはり 127.0.0.1:50000 を見ていました。 [Android emulator access redir port from other host - android] (https://android.developreference.com/article/26634092/Android+emulator+access+redir+port+from+other+host ) という記事があったのですが、何時のモノなのか公式(的)なモノなのかも分かりません。 内容も結局私がやったように (redir した)ポートへの転送をもう1つ…というだけでしたので、どうにしろ役には立たなかったです。 > AndroidアプリでTCP/IPの通信をやりたく、現在勉強中 ということで「エミュレータへのLAN側からのアクセス」は主題ではありませんので、このまま調査を続けても「勉強」は進まない感じがします。 どこかで区切りをつけて、ホストPCとエミュレータの通信で進めるか、Wifi (等)で実機を LAN に繋げて進めるかにしたほうが良いように思います。
HYDESA

2021/11/04 09:02 編集

jimbeさん ご教示ありがとうございました。 いろいろと助かりました。 そうですね、これ以上やっても進みそうにないので、 実機で確認するなりしてみます。 いろいろとありがとうございました。
guest

回答1

0

自己解決

実機で確認したら受信しました。
エミュレーターの不具合かと思われます。
jimbeさん、いろいろとありがとうございました。

投稿2021/11/09 07:12

HYDESA

総合スコア8

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問