システムプログラム（第6週）: marshaling/unmarshaling


# システムプログラム（第6週）: marshaling/unmarshaling

筑波大学 システム情報系 情報工学域
新城 靖
<yas@cs.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~syspro/2012/2012-05-23 /marshaling.html
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~syspro/2012/
http://www.coins.tsukuba.ac.jp/~yas/

## marshaling/unmarshaling

## プログラム中のデータ項目とネットワーク上を流れるメッセージに対応づける。

marshaling (整列化)
メモリ中からデータ項目を集めて、ネットワークでメッセージとして
転送するのに適した形式にまとめる。
unmarshaling (非整列化)
逆。

英語の綴りは、l が１つのものと２つのもの(イギリス綴り)がある。教科書によって違う。

図? marshalingとunmarshaling

４個の要素からなる構造体を整列化して送信している。

整数
文字列
ビットマップデータ（可変長）のバイト数
ビットマップデータ（可変長）の本体

整列化する基本的な方法

構造体や配列の要素を先頭から順にバッファに追加する。
可変長のデータの場合、まず、要素数を追加し、それに続いて本体を追加する。

ネットワークからデータを受け取ると、先頭から解釈して元のデータを再現す
る。

ネットワーク上を流れている時には、整列化された
データの先頭にはネットワークのヘッダが付加されている。

### 整数のmarshaling

### 分散プログラムでは、メッセージを送信するプロセスと受信するプロセスが異
なる CPU で実行されることがある。整数をmarshalingする時には、次のような
点を考慮する必要がある。

ワード(基本的な整数データ)が 8bit/16bit/32bit/64bit と違うことがある。
C 言語の int 型のビット数が違う。
1バイトのビット数は、現在は、8ビットのものが主流。
(1バイトが9ビットのものもあった。)
メモリには、バイト単位で番地が付けられているものが主流。
(ビット単位、ワード単位で番地を付ける方法も考えられる。)
バイト・オーダが違うことがある。

### バイト・オーダ

### 整数を送るだけでも、バイトオーダに気をつける必要がある。

Ｃ言語で扱える整数

1 バイト(char)
2バイト(short)
4バイト(long)

(現在のコンピュータのほとんどは、バイト単位でアドレスを付けているので、
１バイトの整数については、バイトオーダの問題はない。)

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ビット

#### htonl() を使った整数の送信

unsigned long int hostlong, netlong;
hostlong = 0x12345678 ;
netlong = htonl( hostlong );
send(conn, &netlong, sizeof(netlong), 0);

### snprintf()/strtol()

### snprintf() で文字列に直して送り、strtol() や atoi() でもどす方法もある。
文字列文化。インターネットのアプリケーションでよく使われる。

送信側:

char buf[BUFSIZE];
hostlong = 0x12345678 ;
snprintf(buf,BUFSIZE,"%d\n",hostlong );
send(conn, buf, strlen(buf), 0);

思ったほど遅くはない。

注意：sscanf() は、整数をデコードするために使う分には問題ないが、
文字列を受け取るために使うとバッファ・オーバーフローが生じる可能性があるので、
使わない方がよい。

### 文字列のmarshaling

文字コードを合わせる。
複数バイトの場合、バイト・オーダも合わせる。

Last updated: 2012/05/21 17:36:59