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

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

新規登録して質問してみよう
ただいま回答率
85.48%
ネットワーク

ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

Q&A

2回答

3303閲覧

Processingでサーバークライアント間のデータ通信をしたい

mkoban777

総合スコア13

ネットワーク

ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

0グッド

0クリップ

投稿2020/09/08 04:14

編集2020/09/08 23:49

Processingでサーバーとクライアントのプログラムを作って通信させたいと考えています。
初めてのプロセッシングという書籍の19章を参考にしていますが、そのままサンプルコードを使ってもうまくいきません。
processingのバージョンは3.5.4、windows10にて実行しています。

質問

互いの画面にellipseでお絵描きするプログラムを実行してみましたが、なぜか相手から送信された座標にellipseを描くことができません。
クライアントプログラムのvoid clientEvent(Client client) 内のellipse(vals[0], vals[1], 16, 16);が機能しないのはなぜでしょうか。
試しにvoid draw内にellipse(vals[0], vals[1], 16, 16);を入れてみるとうまくいくのですが、その理由がわかりません。

サーバー側プログラム

import processing.net.*; Server server; String incomingMessage = ""; void setup() { size(400, 200); server = new Server(this, 5204); fill(0); } void draw() { background(255); text(incomingMessage, 20, 50); Client client = server.available(); if (client != null) { incomingMessage = client.readStringUntil('\n'); server.write(incomingMessage); } } void serverEvent(Server server, Client client) { incomingMessage = "A new client has connected:" + client.ip(); println(incomingMessage); }

クライアント側プログラム

import processing.net.*; Client client; int[] vals = new int [2]; void setup() { size(200, 200); client = new Client(this, "127.0.0.1", 5204); background(255); fill(0, 100); noStroke(); for(int i =0; i<2; i++){ vals[i] = 0; } } void draw() { } void clientEvent(Client client) { rect(100,100,50,50); String in = client.readString(); if (in != null) { in = in.trim(); println( "Receiving:" + in); vals = int(split(in, ",")); ellipse(vals[0], vals[1], 16, 16); } } void mouseDragged() { String out = mouseX + "," + mouseY + "\n" ; ellipse(mouseX, mouseY, 16, 16); client.write(out); println("Sending: " + out); }

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

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

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

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

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

thkana

2020/09/08 22:50

質問は一件一葉(紙じゃないですけど)にしていただけませんか。
mkoban777

2020/09/08 23:46

承知しました。
guest

回答2

0

mkoban777さんはご存じでしょうが、「初めてのProcessing」は翻訳本です。
原著者のHPにコードが載っています。
multiuser client | Learning Processing 2nd Edition

細かい違いはありますが、大体同じように見えます。

何故このコードが意図通り動かないかですが、答えは足元にありました(著者自身が間違いと言っています^^;
Example 19-6/Exercise 19-5: ellipse() doesn't work in clientEvent · Issue #210 · shiffman/LearningProcessing

プルリクエストも出ています(mkoban777さんの修正と同じような内容)
Fix drawings of other clients not showing in example 19-7 by multimentha · Pull Request #226 · shiffman/LearningProcessing


本にするとき(翻訳時も)に、動作チェックはしないもんなんですかね?

投稿2020/09/12 00:06

編集2023/08/12 09:19
TN8001

総合スコア9326

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

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

mkoban777

2020/09/14 03:02

ご回答ありがとうございます。 間違いだったんですね ~~; 本の内容はわかりやすいのに、、。 プルリクエストのアドレスにあるコードもエラーが多くてまだうまく動かせていません。 まだ解決に至っていませんが、とにかく情報ありがとうございます。
guest

0

そもそもが

互いの画面にellipseでお絵描きするプログラム

ではないと思いますが...

それはともかく、
https://github.com/processing/processing/issues/5992
をみると、benfryさん(ってきっとProcessingの開発者のBen Fryさんだよねぇ?)が

Graphics can/should only be updated inside setup() or draw().

deepl翻訳: グラフィックの更新は setup() か draw() の中でしかできません/すべきではありません。

って言ってます。公式のドキュメントを見るとredraw()を使えば出来そうな気がしますが、Benが言っているのでダメなんでしょう。


その後のコメント欄でのやりとりもあって、その辺盛り込んでみました。

Processing

1import processing.net.*; 2Client client; 3int[] vals = new int [2]; 4void setup() { 5 size(200, 200); 6 client = new Client(this, "127.0.0.1", 5204); 7 background(255); 8 fill(0, 100); 9 noStroke(); 10 for (int i =0; i<2; i++) { 11 vals[i] = 0; 12 } 13} 14String in; 15boolean isServerCall=false; 16boolean isMouseCall=false; 17void draw() { 18 if (isServerCall) { 19 rect(100, 100, 50, 50); 20 if (in != null) { 21 in = in.trim(); 22 println( "Receiving:" + in); 23 vals = int(split(in, ",")); 24 ellipse(vals[0], vals[1], 16, 16); 25 } 26 isServerCall=false; 27 } 28 if( isMouseCall){ 29 ellipse(mouseX, mouseY, 16, 16); 30 isMouseCall=false; 31 } 32} 33void clientEvent(Client client) { 34 in = client.readString(); 35 isServerCall=true; 36 redraw(); 37} 38void mouseDragged() { 39 String out = mouseX + "," + mouseY + "\n" ; 40 client.write(out); 41 println("Sending: " + out); 42 isMouseCall=true; 43 redraw(); 44}

描画はすべてdraw()に任せ、ハンドラからはredraw()経由でdraw()を呼ぶ、という形だとなんだか期待通りに動いているように見えます。

投稿2020/09/09 13:24

編集2020/09/11 22:38
thkana

総合スコア7639

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

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

TN8001

2020/09/09 14:18

> そもそもが Clientを複数立ち上げるんじゃないですかね? > redraw()を使えば出来そうな気がします draw()が何もない状態でredraw()しても意味ないと思いますが、全ストロークを保存したうえでdraw()するというのを端折ってますか? https://processing.org/tutorials/network/ Example 2: Shared drawing canvas のようにdraw()中で受信するようなのが正しいんでしょうかね?
thkana

2020/09/09 23:33

> Clientを複数立ち上げるんじゃないですかね? あぁ、そうか。Processingでそういう使い方したこと無かったんで思いつきませんでしたが、そうするとCllientってコンテナ的になってるのかしら? そのうち調べよう。 redraw()の使い方は勘違いしてました。描画だけやってくれるのかと思ってしまって。draw()をまるごとやるんですね... > draw()中で受信するようなのが正しいんでしょうかね? ソケット通信ならバッファもたっぷりあるでしょうし、今回のような使い方ならdraw()中で受信するのもありでしょうね。大量のデータをやり取りする時にはdraw()ではデータが溢れたりしそうですが。 受信はハンドラでもいいけど、描画はdraw()でやれ、という意味かと思ったのですが。 setup()の最後でnoLoop()して void draw() { rect(100, 100, 50, 50); ellipse(vals[0], vals[1], 16, 16); } void clientEvent(Client client) { String in = client.readString(); if (in != null) { in = in.trim(); println( "Receiving:" + in); vals = int(split(in, ",")); } redraw(); } とするとなんかそれっぽい動きを...いま真面目に見る時間が取れないのであとで(最悪週末)見てみようかしら。
mkoban777

2020/09/14 02:58

ありがとうございます。 いただいたコードを実行してみました。 PC_AでサーバーとクライアントAを実行 PC_BでクライアントBを実行 すると PC_A上ではうまくいくのですが、PC_B上でのクライアントの動きがおかしくなります。 具体的にはクライアントBでの描写はクライアントAに伝わりますが、 クライアントAの描写がほとんどクライアントBに伝わりません。 ちなみにPC_BはノートPCでWIFI接続していますが、そのあたりに原因があるのでしょうか。
mkoban777

2020/09/15 01:55

うまくいかない原因はデータをsplitでとりだすところにありそうです。 vals = int(split(in, ",")); 配列要素数を2つしか作っていないのに、勝手に10個ほど作成し、その最後の要素にy座標を入れてしまいます。でもなぜこんなことが起こるのか、、、
thkana

2020/09/15 12:35

> 配列要素数を2つしか作っていないのに、勝手に10個ほど作成し Cではないので、配列の変数は配列のインスタンスを保持するだけです。 で、TCP/IPの伝送は「バイト単位」でしか管理されないのにx,yが単位としてやり取りできることを期待したプログラムが悪いのかもしれません。x1,y1x2,y2x3,y3...みたいな感じでまとまってデータを受け取ってしまっているのかも。 サーバ側、 server.write(incomingMessage); を server.write(incomingMessage+'\n'); とでもして、クライアント側は String in = client.readString(); を String in = client.readStringUntil('\n'); としたらどうなるでしょう。
thkana

2020/09/16 11:47

あれ、readStringUntil()は区切り文字列が残るんだっけ? だったら server.write(incomingMessage); はそのままでいい。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問