TCPで値を送る。

#  vvvvでTCP通信を使う
TCPを使うことによってvvvv間で、値のやり取りをすることができます。

インタラクティブな作品を作るとき、特にセンサーの設置には物理的な制約が加わります。
たとえばマイク。
マイクで拾った音をトリガーにして、インタラクションを起こしたい。
けれども、マイクの配線を、プロジェクタ付近のPCまで引き延ばせないなんてことがあるかもしれません。
**そんな時は、PCを2台用意して、2台それぞれでvvvvを立ち上げて無線で情報をやり取りしてしまえばいいのです**
え？2台もPCないって？いやでも、センサー側のPCはvvvvが動いて無線が使えれば、ほぼどんなものでも大丈夫です。
映像を書き出す側はスペックが必要ですが、センサーの値を送信する側はスペックは必要となりません。

# 使い方について
何はともあれTCPノードを出しましょう。

TCPには主に下記の2種類があります。

TCP (Network Server)
TCP (Network Client)

サーバー側とクライアント側です。相互通信もできるのですが、この記事を見た方の場合「とにかく数値が一方通行で送れればいい！！」という場合が多いと思いますので、便宜上**サーバー側を送信側**、**クライアント側を受信側**としてこの記事を書きます。

TCP (Network Server)≒送信側
TCP (Network Client)≒受信側

ということですね。

で、まずとにかく接続例を出します。

まずは、**サーバー側（送信側）**から見ていきます。
![saba.png](https://qiita-image-store.s3.amazonaws.com/0/100231/734b1666-c7fc-33ed-a487-4c096518cd76.png)


LFOの値をAsRawに投げてバイナリ化します。バイナリってのは2進数に変えるってことですね。とにかくTCPで送れる形にするってことです。
でバイナリ化された値がTCPノードにつながって送信されています。
このパッチはTCP (Network Server)を選択して「F1キー」を押したときに出てくるヘルプパッチを簡略化したものです。
なので、同じようなものが作りたいときは、ヘルプパッチを出してもらって、余計なものを削除してもらえればすぐできます。


お次に**クライアント側**（受信側）です。
![kura.png](https://qiita-image-store.s3.amazonaws.com/0/100231/88bfe69b-d642-a6da-046f-a342986c0834.png)
まずはサーバー側（送信側）のIPアドレスを調べて、クライアント側のパッチの部分に入れましょう。IPアドレスの調べ方は、**サーバー側（送信側）のPCで**コマンドプロンプトを開いてipconfigを入力して出てくるIPv4アドレスなので間違えないようにちしてください。
（参考　http://asahi-net.jp/support/guide/os/0007.html ）
また、TCPをテストするだけなら、サーバー側（送信側）とクライアント側（受信側）の2つのパッチを1台のPC上で動作させることができます。
この場合IPアドレスはlocalhostと入力すればokです。

TCPノードから受診したバイナリデータをS＋Hノードを介してAsValue(Raw)に入れて、バイナリ化を解除して数字に変換します。
このパッチもTCP (Network Client)を選択して「F1キー」を押したときに出てくるヘルプパッチを簡略化したものなのですが、一部追加している部分があります。画像のオレンジ色の部分です。

なぜここが必要かという話なんですが、そもそも無線というのは不安定なもの。
常に定速で途切れなく情報が送られてくるわけではありません。
なので、一瞬接続が切れてしまう時があります。それが内部の処理でしか見えない場合もあれば、私たちが分かるような長い時間途切れることもあります。
なので、TCP通信が途切れているときは、前の値を保持してね。というものです。
　
なお使っている「S+H」と「＝」は「S+H(Raw)」「＝(Raw)」なので注意してください。


ここまで来て一応、ローカルネットワーク内の2台のPCのvvvvで、TCP通信ができるようになりました。
データが飛んでくるのが分かります。

**ですが実はこれだけれは不十分なのです**

# 「なぜかSpreadで飛んでくる…？」もうひと手間が必要な理由

繰り返しになりますが、TCPをテストするだけなら、サーバー側（送信側）とクライアント側（受信側）の２つのパッチを1台のPCで動作させることができます。この場合IPアドレスはlocalhostと入力すればokでした。
この時は問題なく通信できているように見えます。

しかし、実際に送信側と受信側を別PCで行うと、問題が生じてきます。

**「普通の数字を送っているはずなのに、受信側ではSpreadとして解釈されている…？」**

という現象が生じます。なぜでしょうか？
サーバー側（送信側）は、ひっきりなしにデータをパケットに分割して送ります。
クライアント側（受信側）は、送られてきたパケットを必死に受け取りますが、どこでデーターが区切られるのかわかりません。
なのでクライアントは、とにかく受信した分だけ出力しようとするので、Spreradにして受信した分をそのまま出力してしまいます。

これを回避するためには、終端文字といわれる文字を付けて、ここがデーターの区切りですよ、という風に記載する必要があります。

では、まず**サーバ側（送信側）**から見ていきましょう。
ここでは送信する値がSpreadであることを想定してパッチを作っています。
![s_saba.png](https://qiita-image-store.s3.amazonaws.com/0/100231/f267edd7-6a33-340f-ff37-4cc420971882.png)

まず、Spreadの値をAsStringで文字列に変換します。
次に、＋(StringSpectral)を使って、3つのスプレットをカンマで区切った一つの長い文字列に変換しました。
この文字列の最後に、＋(String)を使って「v」を付けています。
この「v」が区切りの文字として送信されるわけです。(ちゃんとした終端文字もあるみたいですが、私はよく「v」を使います。なんでもいいんでしょうけどね。)

そこからAsRaw（String）に繋いでバイナリ化します。
3つの数値のSpreadは、最終的に1つの長い文字列として送信されます。




次に**クライアント側（受信側）**をみてみましょう。
![s_kura.png](https://qiita-image-store.s3.amazonaws.com/0/100231/9db7a376-439d-f9ca-4f64-65ff7f7c772a.png)

受診側では、受け取ったバイナリデータを、AsString(Raw)で長い文字列に変換します。
次にTokenizer(String)を使って、送信側でつけた「v」を目印に、データーを区切ってゆきます。
さらにSeparate(String)でカンマごとにSpreadにわけで、もとの3つのスプレッドに戻します。
ここではまだ文字列なので、これをAsValue(String)を使って数値に変換します。

この一連の流れを使えば、センサーの値をTCPを使って無線で送ることができます。


# 上手に使うために
センサーから取得した数字を送ることはできますが、もし閾値が決まっているのなら、判定処理をサーバー側で終わらせて、TCPで送るのは0,1のBool値にしたほうがいいかもしれません。
TCPは数字、文字列以外にも、色を送ることができます。AsColor(Raw)などと使ってください。

1つのサーバー側から、複数のクライアント側へデータを送信できます。なので、1つのセンサーの値を複数人で共有することもできます。