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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

6921閲覧

C# ネットワーク間のシリアライズ

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2017/06/13 06:33

編集2017/06/13 08:29

今TCP/IPでクライアントとサーバーの通信をしています。

クライアントのClassをシリアライズし、サーバーに送りたいのですがやり方がイマイチわかりません。

クライアント側

C#

1Sample sampleData = new Samle(); 2 3public static void WriteBinaryData(object sampleDate) 4 { 5 TcpClient client = new TcpClient(); 6 client.Connect("127.0.0.1", 9000); 7 NetworkStream stream = client.GetStream(); 8 9 // BinaryFormatterオブジェクト生成 10 BinaryFormatter formatter = new BinaryFormatter(); 11 formatter.Serialize(stream, sampleData); }

でシリアライズしました。
下記がシリアライズ対象のクラスです。(中身が""なのは気にしないでください。)

C#

1[Serializable] 2 class Sample 3 { 4 public string maker = ""; 5 public string name = ""; 6 public string bodytype = ""; 7 public string model = ""; 8 public string distance = ""; 9 public string cc = ""; 10 public string transmission = ""; 11 public string color = ""; 12 public string price = ""; 13 }

サーバー側のデシリアライズメソッド(抜粋)

C#

1 public void Receive(NetworkStream stream) 2 { 3 BinaryFormatter formatter = new BinaryFormatter(); 4 Sample sampleDate = new Sample(); 5 sampleDate = (Sample)formatter.Deserialize(stream); 6 }

サーバー側も同じように下記のクラスを作りました。

C#

1[Serializable] 2 class Sample 3 { 4 public string maker = ""; 5 public string name = ""; 6 public string bodytype = ""; 7 public string model = ""; 8 public string distance = ""; 9 public string cc = ""; 10 public string transmission = ""; 11 public string color = ""; 12 public string price = ""; 13 }

そうすると{"アセンブリ 'クライアント, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' が見つかりません。"}と出てきます。

どうすればデシリアライズがうまくいくのでしょうか?
またDLL??がどうこうと参考したサイトには記載されていますがどういうことでしょうか?
無知で全然わかっておりませんがよろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

こんな感じで如何でしょう?

C#

1namespace TestModel 2{ 3 [Serializable] 4 public class TestClass 5 { 6 public string Message { get; set; } 7 } 8}

C#

1namespace SenderApp 2{ 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 var formatter = new BinaryFormatter(); 8 var obj = new TestModel.TestClass { Message = "Hello!" }; 9 byte[] dat; 10 using (var stream = new MemoryStream()) 11 { 12 formatter.Serialize(stream, obj); 13 stream.Seek(0, SeekOrigin.Begin); 14 dat = stream.ToArray(); 15 } 16 using (var socket = new TcpClient("localhost", 65000)) 17 { 18 using (var stream = socket.GetStream()) 19 { 20 stream.Write(dat, 0, dat.Length); 21 } 22 } 23 } 24 } 25}

C#

1namespace ServerApp 2{ 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 var listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 65000); 8 listener.Start(); 9 var bytes = new List<byte>(); 10 using (var client = listener.AcceptTcpClient()) 11 { 12 Console.WriteLine("受信開始"); 13 using (var stream = client.GetStream()) 14 { 15 do 16 { 17 var res = stream.ReadByte(); 18 if (res == -1) break; 19 bytes.Add((byte)res); 20 } while (stream.DataAvailable); 21 } 22 } 23 24 using (var stream = new MemoryStream(bytes.ToArray())) 25 { 26 var formatter = new BinaryFormatter(); 27 var obj = formatter.Deserialize(stream); 28 var testModel = obj as TestModel.TestClass; 29 if(testModel != null) 30 { 31 Console.WriteLine("{0}を受信しました。", testModel.GetType()); 32 Console.WriteLine("メッセージは:{0}", testModel.Message); 33 } 34 } 35 36 } 37 } 38}

投稿2017/06/13 10:33

hihijiji

総合スコア4150

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

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

退会済みユーザー

退会済みユーザー

2017/06/13 10:39

ありがとうございます。 イマイチ理解していないのですが、一番上のコード、namespace TestModelはどこに書いたらよいのでしょうか? クライアントアプリ側で新しくクラスを作成してそこに書くのでしょうか?それともサーバー側ですか? 私は理解できていないため、私自身が質問した文章にはクライアントアプリ、サーバーアプリの両方に新しくクラスを作成し、その新しいクラスに[Serializable]・・・省略・・・としていますが根本的に間違っているのでしょうか? よろしくお願いいたします。
hihijiji

2017/06/14 01:11

同じような別のクラスを作るのではなく、同じクラスを参照する必要があります。 ですから受け渡すクラスは、クライアントとサーバの双方が参照する別プロジェクトに納めるのがやり易いと思います。
退会済みユーザー

退会済みユーザー

2017/06/14 02:32

クライアントアプリ、サーバーアプリ、受け渡しアプリの計3つのプロジェクトを作成する。 つまり、クライアントが送信する内容は受け渡しアプリへ。サーバーが受信する内容は受け渡しアプリから受け取る。という事でしょうか?受け渡しアプリが仲介するという認識で合っていますでしょうか?? また、上記のだった場合、仲介なしでクライアントとサーバーだけでのやり取りは難しいのでしょうか? よろしくお願いいたします。
workaholist

2017/06/14 02:37

クラス定義の入ったdllを作って、クライアントとサーバーの両方から参照するだけですがそんなに問題ありますか?
退会済みユーザー

退会済みユーザー

2017/06/14 02:45

クラス定義の入ったdllというのはhttp://www.eonet.ne.jp/~maeda/cs/hellodll.htmを参考にすれば良いでしょうか? 全然理解できていなくてすみません。。
workaholist

2017/06/14 02:58

hihijijiさんの仰る例ですと、  ・「TestClass」クラスを含むクラスライブラリのプロジェクトを作成  ・サーバー、クライアントから上記プロジェクトをプロジェクト参照するなり、ビルドしたdllを参照するなりする だと思います。
退会済みユーザー

退会済みユーザー

2017/06/14 03:24 編集

上記のコードでうまく動きました。 長々と私の質問にご対応してくださり本当にありがとうございました。 こちらを参考に自分で作成しているプログラムに適応させていきたいと思います!
guest

0

今のままでは、別物をシリアライズしようとしているからだめ。
BinaryFormatterは、型にうるさい。同じDLLの同じ名前しかだめ。
この方の縛りから逃れるには、JSONなりを使うか、
サーバとクライアントとは別に、シリアライズ用のプロジェクトを作り、それを両方から参照する。

参考:http://blog.xin9le.net/entry/2017/06/11/182640
最近読んだ記事というだけだけど。

投稿2017/06/13 08:50

編集2017/06/13 08:58
kiichi54321

総合スコア1984

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問