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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

ソケット

TCP/IPにおいて、IPアドレスとサブアドレスであるポート番号を組み合わせたネットワークアドレスのことを呼びます。また、ソフトウェアアプリケーションにおいて、TCP/IP通信を行う為の仮想的なインターフェースという意味もある。

Android Studio

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

Q&A

解決済

2回答

1747閲覧

ソケット通信においてPC-Android間の通信ができない

gken

総合スコア4

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

ソケット

TCP/IPにおいて、IPアドレスとサブアドレスであるポート番号を組み合わせたネットワークアドレスのことを呼びます。また、ソフトウェアアプリケーションにおいて、TCP/IP通信を行う為の仮想的なインターフェースという意味もある。

Android Studio

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

0グッド

1クリップ

投稿2021/11/03 11:33

編集2021/11/12 10:45

PC-Android間の通信を実現したい

TCPを使用したソケット通信にてクラスオブジェクトを送受信したいです。
【Java】TCP通信を利用したデータ送受信 | のんぽぐを参考にプログラミングの学習を進めています。このサイトではPC-PC間のソケット通信について書かれていると思いますが、PC-Android間での通信を実現したいです。

PC-Android間で
プログラムを実行したとき、実行結果に示したようになり、Server(PC側)のプログラムの24行目
UserInformation cIU =(UserInformation)objectInputStream.readObject();
が超えられません。eclipse上では問題や警告は出ていません。

ClassNotFoundExceptionで検索したのですが解決策が分かりません。
お力添えいただけないでしょうか。

Server画面(PC) 実行結果

java Server_ver3java.lang.ClassNotFoundException: com.websarva.wings.android.clientver3.UserInformation at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:720) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1925) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1808) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2099) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1625) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:465) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:423) at Server_ver3.main(Server_ver3.java:24)

該当のソースコード

###Serverプログラム(PC)

Java

1package com.websarva.wings.android.clientver3; 2 3import java.io.IOException; 4import java.io.ObjectInputStream; 5import java.net.ServerSocket; 6import java.net.Socket; 7 8public class Server_ver3 { 9 10 public static ServerSocket serverSocket = null; 11 public static Socket socket =null; 12 13 public static void main(String[] args) { 14 15 ObjectInputStream objectInputStream = null; 16 17 try { 18 System.out.println("aaa");//デバッグのため 19 serverSocket = new ServerSocket(2001); 20 socket = serverSocket.accept(); 21 System.out.println("bbb");//デバッグのため 22 23 objectInputStream = new ObjectInputStream(socket.getInputStream()); 24 System.out.println("ccc");//デバッグのため 25 26 UserInformation cIU =(UserInformation)objectInputStream.readObject();//24行目 27 System.out.println("eee");//デバッグのため 28 29 objectInputStream.close(); 30 serverSocket.close(); 31 32 System.out.println(cIU.current_latitude); 33 System.out.println(cIU.current_longitude); 34 35 }catch(ClassNotFoundException e) { 36 e.printStackTrace(); 37 }catch(IOException e) { 38 e.printStackTrace(); 39 } 40 } 41 42} 43

###UserInformationクラス(クラスオブジェクト)

java

1package com.websarva.wings.android.clientver3; 2 3import java.io.Serializable; 4 5public class UserInformation implements Serializable { 6 7 public double current_latitude;//現在地 緯度 8 public double current_longitude;//現在地 経度 9 10 11 public void setcurrent_latitude(double inputcurrent_latitude) { 12 this.current_latitude = inputcurrent_latitude; 13 } 14 15 public void setcurrent_longitude(double inputcurrent_longitude) { 16 this.current_longitude = inputcurrent_longitude; 17 } 18}

###Clientプログラム(Android)

Java

1package com.websarva.wings.android.clientver3; 2 3import androidx.appcompat.app.AppCompatActivity; 4 5import android.os.Bundle; 6 7import java.io.IOException; 8import java.io.ObjectOutputStream; 9import java.net.Socket; 10import java.net.UnknownHostException; 11 12public class MainActivity extends AppCompatActivity { 13 14 public static Socket socket = null; 15 public static String host = "192.168.11.2"; 16 public static int port = 2001; 17 18 public static UserInformation cUI = new UserInformation (); 19 20 @Override 21 protected void onCreate(Bundle savedInstanceState) { 22 super.onCreate(savedInstanceState); 23 setContentView(R.layout.activity_main); 24 25 cUI.setcurrent_latitude(35.0); 26 cUI.setcurrent_longitude(139.0); 27 28 29 new Thread (new Runnable(){ 30 public void run(){ 31 32 ObjectOutputStream objectOutputStream = null; 33 34 try{ 35 socket = new Socket(host,port); 36 objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); 37 38 objectOutputStream.writeObject(cUI); 39 40 objectOutputStream.close(); 41 socket.close(); 42 43 } catch (UnknownHostException e) { 44 e.printStackTrace(); 45 } catch (IOException e) { 46 e.printStackTrace(); 47 } 48 49 } 50 }).start(); 51 } 52}

###パーミッション

xml

1<manifest > 2 <uses-permission android:name="android.permission.INTERNET"/> 3 <application ~ 4 </application> 5</manifest>

#試したこと

Client(Android側)のプログラムを少しだけ変更しPC(Server)-PC(Client)で問題なく実行できていることを確認しています。そのときのPC(Client)プログラムが以下になります。
###ClientをPCにした場合

java

1import java.io.IOException; 2import java.io.ObjectOutputStream; 3import java.net.Socket; 4import java.net.UnknownHostException; 5 6public class Client_ver3 { 7 public static Socket socket = null; 8 public static String host = "192.168.11.2"; 9 public static int port = 2001; 10 11 public static UserInformation cUI = new UserInformation (); 12 13 public static void main(String[] args) { 14 15 cUI.setcurrent_latitude(35.0); 16 cUI.setcurrent_longitude(139.0); 17 18 19 ObjectOutputStream objectOutputStream = null; 20 21 try{ 22 socket = new Socket(host,port); 23 objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); 24 25 objectOutputStream.writeObject(cUI); 26 27 objectOutputStream.close(); 28 socket.close(); 29 30 } catch (UnknownHostException e) { 31 e.printStackTrace(); 32 } catch (IOException e) { 33 e.printStackTrace(); 34 } 35 } 36

###実行結果(PCをClientにした際の結果)
aaa
bbb
ccc
eee
35.0
139.0

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

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

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

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

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

jimbe

2021/11/03 15:18

因みにすべてのクラスにおいて package は指定されておらず、UserInformation クラスは同じファイル(一方からもう一方へコピペとかで)なのですね?
gken

2021/11/04 06:25

Clientはpackageしています。 serInformation クラスは同じファイル(ClientからServerへコピペ)です。
gken

2021/11/04 06:35

解決することができました。 ありがとうございました。 ソースコードにpackageを追加したものに修正しました。
guest

回答2

0

ベストアンサー

プログラムを実行したとき、実行結果に示したようになり、Server(PC側)のプログラムの24行目UserInformation cIU =(UserInformation)objectInputStream.readObject();が超えられません。eclipse上では問題や警告は出ていません。
ClassNotFoundExceptionで検索したのですが解決策が分かりません。

java

1 }catch(ClassNotFoundException e) { 2 System.out.println("ClassNotFoundException e");

ほんとうに24行目で発生しているのか、ほんとうにUserInformationクラスがみつからないのか、上記処理ではわかりませんね。以下のように書き換えてその結果を提示してはいかがかと。

java

1 }catch(ClassNotFoundException e) { 2 e.printStackTrace();

また、 serialVersionUID を省略すると、自動的に何かが設定されますが、環境により異なる結果となった経験があります(Windows <-> Linux)。だから、なんでもいいので明示してみたらどうなりますか。

see: https://www.google.co.jp/search?q=java+serialVersionUID

diff

1import java.io.Serializable; 2public class UserInformation implements Serializable { 3+ private static final long serialVersionUID = 12345L;

投稿2021/11/03 12:29

編集2021/11/03 12:31
shiketa

総合スコア4061

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

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

gken

2021/11/03 14:15 編集

try文の例外処理の部分を System.out.println("ClassNotFoundException e"); から e.printStackTrace(); へ変更しました。変更後の実行結果こちらになります。 at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:720) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1925) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1808) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2099) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1625) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:465) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:423) at Server_ver3.main(Server_ver3.java:24)
gken

2021/11/03 13:44

質問のソースコードの方も合わせて変更させて頂きました。
gken

2021/11/03 14:31 編集

serialVersionUIDについて質問させてください。デシリアライズの際に、ロードしようとするクラスのserialVersionUIDとシリアライズオブジェクトが保持するserialVersionUIDの比較が行われ、異なる場合は例外が発生する。と調べたら出てきました。そのため、Server側、Client側のUserInformationクラス(クラスオブジェクト)のserialVersionUIDは同一の値を使用するという認識でいいでしょうか。
shiketa

2021/11/03 23:44 編集

> 変更後の実行結果こちらになります。 at java.net.URLClassLoader.findClass(URLClassLoader.java:382) 何故、すべてを晒さないのでしょうか。ClassNotFoundException のメッセージに、どのクラスが見つからなかったのかが明記されているとおもうのですが。ま、いいです。 -- > そのため、Server側、Client側のUserInformationクラス(クラスオブジェクト)のserialVersionUIDは同一の値を使用するという認識でいいでしょうか。 そうです。そしてこのコメントを読む限り、Server側とClinet側のソースは異なる、ということなのですね。そうなのであれば、もしかしたらパッケージも異なっているのではないでしょうか。ObjectXXStreamでシリアライズ/デシリアライズをしたいのであれば、最低限FQCNは一致している必要があります。 まぁ、そもそも発生している例外が ClassNotFoundException なので、serialVersionUID以前のはなし。だから、「デシリアライズしようとしているUserInformationクラスへのクラスパスが定義されていない」と考えるのが本筋だとおもいます。
shiketa

2021/11/03 23:49

# クライアント側でjava.lang.Stringをシリアライズし、サーバ側で mypkg.Stringクラスにデシリアライズしようとしているのではないですか、ということです。
gken

2021/11/04 05:23

日を跨いでの返信で申し訳ありません。 コピペしたServer側の実行画面に不備がすみませんでした。 正しくはこちらになります。 java Server_ver3java.lang.ClassNotFoundException: com.websarva.wings.android.clientver3.UserInformation at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:720) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1925) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1808) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2099) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1625) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:465) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:423) at Server_ver3.main(Server_ver3.java:24) shiketaさんがおっしゃる通りパッケージを揃えて再度やってみます。
gken

2021/11/04 06:20

Android(Client)のパッケージである package com.websarva.wings.android.clientver3; をPC(Server)に追加しました。 すると、実行結果(PCをClientにした際の結果)と同じ結果を得られました。 shiketaさんのご指摘通り ”最低限FQCNは一致している必要”が出来ていませんでした。
gken

2021/11/04 06:33

無事にうまく受信できました。 ありがとうございました。 ソースコードにpackageを追加したものに修正しました。
dodox86

2021/11/04 07:00

他回答欄でいただいたコメントですが、JavaのRMIの件も含め、私もこれまで知らなかった新たな知見を得られました。高評価させていただきました。
guest

0

ざっくり言えば、同じ java だからと言って(同じ java ファイルを使っていても) PC と Android でシリアライズしたモノが同じとは限りません。
その場合でもどうしてもシリアライズして受け渡ししたいのであれば、シリアライズ/デシリアライズの処理を自ら書く必要があります。

ただ、ClassNotFound だと(readObject が)どのクラスかが分からない状態ですので、シリアライズとかよりも、通信フォーマットを独自に設計してデータをやり取りすることになりそうな気がします。

投稿2021/11/03 12:05

編集2021/11/03 12:11
jimbe

総合スコア13209

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

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

gken

2021/11/03 12:15

解答ありがとうございます。 UserInformation cIU =(UserInformation)objectInputStream.readObject(); デシリアライズではないということでしょうか。
jimbe

2021/11/03 12:25

writeObject でシリアライズし、 readObject でデシリアライズするというのは PC でも Android でも同じです。 問題は、Android でのシリアライズデータと PC でのデシリアライズ処理がマッチしていないことでしょう。 UserInformation を丸ごと送受信するのではなく、そのデータを一つずつ送受信したほうが簡単かと思います。
shiketa

2021/11/03 12:44

jimbeさんの「そのデータを一つずつ送受信したほうが」という指摘が、たとえばテキストで(Stringクラスをシリアライズしてではなく)、たとえばJSON形式で、というはなしなのであれば、わたしもその案に全面的に賛成です。
jimbe

2021/11/03 15:15

> ~ 環境が異なっても、直列化仕様に則っているのであれば ~ その辺りのはっきりした(出来る/出来た、可能/不可能とかの)記述が見つからないでいます。そのために「~ がマッチしていないことでしょう。」というあやふやな表現となってしまいました。 > そのデータを一つずつ送受信したほうが は、まさしく shiketa さんの仰る通りです。
gken

2021/11/03 16:13

お二方ありがとうございました。 他の方法も視野に入れながらもう暫くやってみようと思います。
dodox86

2021/11/03 16:40

Android上でシリアライズしたデータをAndroid上でファイルにいったん保存するなり、あるいはバイナリ列を直接でもいいからサムチェックするなりして、PC上でシリアライズした場合と同じサム値(MD5でもSHA256でもなんでも)になれば、バイナリでのシリアライズ/デシリアライズに問題があるかないか疑念が消えるのではないでしょうか。
dodox86

2021/11/03 16:53

私だったら、Javaのバージョンが同じでも違うVMで動くものでバイナリのシリアライズ、デシリアライズは不安が残るので採用しませんが、、、Androidは.classファイルではなく最終的には.dexファイルで、VMも違い、ART(Android RunTime)です。ただ、シリアライズした結果がそれぞれで同じか、私自身も実際に確認をしたことはありません。
shiketa

2021/11/04 00:43

dodox86さん。わたしの個人的な思い込みだとおもいますが、オブジェクトのシリアライズ/デシリアライズの仕掛けは、rmiを実現するためもあったのではないかと捉えています。 https://docs.oracle.com/javase/jp/1.5.0/guide/rmi/ 異なるVMの間で、異なるJavaのバージョン間で、異なる環境の間で、リモートのメソッドを実行できるようにするための基盤となる仕掛け。だからわたしはこの仕掛け自体は信用しています。
dodox86

2021/11/04 01:03

shiketaさん、コメントに対するフォローの情報どうもありがとうございます。RMIのことについてはまったく意識していませんでしたが、それに照らすとその通りですね。興味がわいたので私も今、検証しているのですが、まずPC上での話ですとOpenJDK 8とOracle SE 11のファイルへのシリアライズの結果(サム値)は同じでした。Android上でも同じかどうか確認しようとしているところです。
gken

2021/11/04 06:37

jimbeさん、shiketaさん、dodox86さん 解決することが出来ました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問