システムプログラム(第6週): marshaling/unmarshaling 
                                       筑波大学 システム情報系 情報工学域
                                       新城 靖
                                       <yas@cs.tsukuba.ac.jp>
このページは、次の URL にあります。
	http://www.coins.tsukuba.ac.jp/~syspro/2013/2013-05-22
/marshaling.html
あるいは、次のページから手繰っていくこともできます。
	http://www.coins.tsukuba.ac.jp/~syspro/2013/
	http://www.coins.tsukuba.ac.jp/~yas/
プログラム中のデータ項目とネットワーク上を流れるメッセージに対応づける。
-  marshaling (整列化)
 -  メモリ中からデータ項目を集めて、ネットワークでメッセージとして
転送するのに適した形式にまとめる。
 -  unmarshaling (非整列化)
 -  逆。
 
英語の綴りは、l が1つのものと2つのもの(イギリス綴り)がある。教科書によって違う。
図? marshalingとunmarshaling
4個の要素からなる構造体を整列化して送信している。
-  整数
 -  文字列
 -  ビットマップデータ(可変長)のバイト数
 -  ビットマップデータ(可変長)の本体
 
整列化する基本的な方法
-  構造体や配列の要素を先頭から順にバッファに追加する。
 -  可変長のデータの場合、まず、要素数を追加し、それに続いて本体を追加する。
 
ネットワークからデータを受け取ると、先頭から解釈して元のデータを再現す
る。
ネットワーク上を流れている時には、整列化された
データの先頭にはネットワークのヘッダが付加されている。
分散プログラムでは、メッセージを送信するプロセスと受信するプロセスが異
なる CPU で実行されることがある。整数をmarshalingする時には、次のような
点を考慮する必要がある。
-  ワード(基本的な整数データ)が 8bit/16bit/32bit/64bit と違うことがある。
C 言語の int 型のビット数が違う。
 -  1バイトのビット数は、現在は、8ビットのものが主流。
(1バイトが9ビットのものもあった。)
 -  メモリには、バイト単位で番地が付けられているものが主流。
(ビット単位、ワード単位で番地を付ける方法も考えられる。)
 -  バイト・オーダが違うことがある。
 
整数を送るだけでも、バイトオーダに気をつける必要がある。
C言語で扱える整数
- 1 バイト(char)
 -  2バイト(short)
 -  4バイト(long)
 
(現在のコンピュータのほとんどは、バイト単位でアドレスを付けているので、
1バイトの整数については、バイトオーダの問題はない。)
2バイト、または、4バイトの整数をメモリに保存する方法
: メモリの下位番地に上位バイトを置くか下位バイトを置くか
-  リトルエンディアン
 -  下位番地に下位バイトを置く。x86 (Intel Pentium/Core, AMD Athlon/Phenom)。
 -  ビッグエンディアン。
 -  下位番地に上位バイトを置く。PowerPC, SPARC, m68k
 
PowerPC は、両方切り替え可能だが、ビッグエンディアンで使うことが多い。

図? バイト・オーダ
-  送信側、または、受信側で相手に合わせて変換する。バイトオーダが同
じ場合は何もしない。
 -  標準的なバイトオーダ(ネットワーク・バイト・オーダ) を定める。送
信側では、ネットワークにデータを流す時には、常に自分自身のバイト・オー
ダ(ホスト・バイト・オーダ)をネットワーク・バイト・オーダに変換する。
受信側では、ネットワーク・バイト・オーダから自分のホスト・バイト・オー
ダに変換する。
 
 
現在、ネットワーク・バイト・オーダとしては、ビッグエンディアンが広く
使われている。
-  TCP/IP の IP アドレスやポート番号
 -  XDR
 
| 名前 | 	方向 | 	ビット数 | 
| uint32_t htonl(uint32_t hostlong) | 	ホストからネットワークへ変換 | 	32ビット | 
| uint16_t htons(uint16_t hostshort) | 	ホストからネットワークへ変換 | 	16ビット | 
| uint32_t ntohl(uint32_t netlong) | 	ネットワークからホストへ変換 | 	32ビット | 
| uint16_t ntohs(uint16_t netshort) | 	ネットワークからホストへ変換 | 	16ビット | 
unsigned long int hostlong, netlong;    
hostlong = 0x12345678 ;    
netlong = htonl( hostlong );    
send(conn, &netlong, sizeof(netlong), 0);
snprintf() で文字列に直して送り、strtol() や atoi() でもどす方法もある。
文字列文化。インターネットのアプリケーションでよく使われる。
送信側:
    char buf[BUFSIZE];
    hostlong = 0x12345678 ;    
    snprintf(buf,BUFSIZE,"%d\n",hostlong );
    send(conn, buf, strlen(buf), 0);
思ったほど遅くはない。
注意:sscanf() は、整数をデコードするために使う分には問題ないが、
文字列を受け取るために使うとバッファ・オーバーフローが生じる可能性があるので、
使わない方がよい。
-  文字コードを合わせる。
 -  複数バイトの場合、バイト・オーダも合わせる。
 
Last updated: 2013/05/21 17:27:12
 
 Yasushi Shinjo / <yas@cs.tsukuba.ac.jp>