「夫を成功」へ導く妻の秘訣 座談会

TCP/IP通信すなわちパケット通信するためにはMACアドレスが必要で、そのためにはARPを行い、ブロードキャストを送信すると考えています。

そこで、最初の段階であるブロードキャストはTCP/IPモデルでどの層でどのような働きをしているのでしょうか?

最初の段階(ブロードキャスト)ではMACアドレスは分からないはずなので下位層のネットワークインターフェイス層ではイーサネットヘッダやイーサネットトレーラは付かず、中途半端なカプセル化になるのでしょうか?

通信に精通している方は、この質問の意図も分かりにくいと思います。。すみません。
ご教授お願いしますm(__)m

このQ&Aに関連する最新のQ&A

A 回答 (2件)

回答は大体No.1氏がされているので、補足的に。


「ブロードキャスト」という英語をそのまま日本語に翻訳すると「放送」で、つまりはあて先を指定せずにすべての端末宛にパケットを投げることをネットワーク通信の世界では「ブロードキャスト」と呼んでいます。
で、このブロードキャストは、ネットワーク層(L3層;IP)とデータリンク層(L2層;イーサネット)それぞれで定義されています。

ARPといのは位置づけ的にはL3層のプロトコルですが、機能的にはL3層とL2層の間を取り持つような働きをします。
あて先IPに対応するMACアドレスをノードが保持していない場合、ARPを利用してMACアドレスの探索(ARP request)を行います。このとき、L2層では、データリンク層レベルでブロードキャストを行い、同じネットワーク内に存在するすべてのノードに対して問い合わせを行うのです。

おそらく、質問者さんはこのARPによるブロードキャストをIPのブロードキャストと勘違いされたのではないかと想像します。

なお、IPでブロードキャストを行う場合は、No.1氏が回答されたとおり、そのままL2層でブロードキャストアドレスがあて先アドレスに設定されます。

…回答になったかな?
    • good
    • 0

OSI階層でいえば、TCP/IPは


イーサネット: データリンク層 MACアドレスで宛先を指定
IP: ネットワーク層 IPアドレスで宛先を指定
TCP/UDP: トランスポート層 ポート番号で宛先を指定
といった対応になります。

ネットワーク層でも、ユニキャスト(相手のIPアドレスを宛先に指定)の他に、ブロードキャスト(IPアドレスのホスト部が全部1のアドレスを宛先に指定)というものがあるわけですが、
それとは別に、データリンク層でも、ユニキャスト(相手のMACアドレスを宛先に指定)の他に、ブロードキャスト(MACアドレスは全部1のアドレスを宛先に指定)というものがあります。

通常の、TCP/IP通信では、宛先に指定したIPアドレスを元に、データリンク層ではその宛先に対応するMACアドレスを指定して送信します。
宛先IPアドレスがブロードキャストアドレスだった場合は、宛先MACアドレスをブロードキャストにする、という処理を行うことで、
ブロードキャストも含めて、TCP/IPレベルでの送信相手の指定が、そのままデータリンク層での送信相手の指定としても機能するようになるわけです。

で、そのIPアドレスから、その宛先に合致するMACアドレスを取得する方法としてARPがあるわけですが、
ARPはIPと同階層のプロトコルであり、そこからデータリンク層に対してはブロードキャストMACアドレス(FF:FF:FF:FF:FF:FF)を相手に指定してパケットを送出しているのです。
http://www.atmarkit.co.jp/fwin2k/network/baswinl …

データリンク層では、送受信しているデータがIPでもARPでも、イーサネットヘッダやトレーラが付くなどといったイーサネットとしてのデータはまったく同じです。
そうして送る中身だけが違うということになります。
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QUDP通信におけるbind関数について

初めて質問させていただきます。よろしくお願いします。

最近、ネットワークプログラミングの勉強をしているのですが、bindについてよくわからなくなってきました・・・。よろしければご教授願います。

質問内容は以下の通りです。
(1)bindにおける設定内容は、「相手側のIPとポート番号」なのか「自分側のIPとポート番号」なのか?
 色々なところを調べてみましたが、「IPとポート番号」を設定する、としかかかれてなく、いったいどっちなのかがわからなくなってきました・・・。

(2)UDP通信において、bindは必要なのか?
 サーバ-クライアントの関係が曖昧なUDP通信において、bindというのは必要なのでしょうか。
私の認識では例えば、「recv関数」などを使い受信待ちをする場合はbindが必要だが、送信だけの場合には不要であるとなっています。

この認識はあっているのでしょうか。
拙文ですが、どうか教えていただきたく <(_ _*)>

Aベストアンサー

TCP/UDP通信がどのように働くかを考えれば、疑問の答えが分かるのでは?
bindについて言えば
「OSはマシンに届いたパケットを如何にして該当プログラムに届けるか?」
です。
自分のポート番号をOSに教えてあげなければ、OSは着信したパケットをどのプログラム(プロセス)に届けるか分からないでしょう。それをするのがbindの役割です。
従って(1)は自ポート番号。IPは複数IPを持っているマシンで一部IPでのみ受け付ける場合に必要ですね。
一般的にサーバでbindするタイミングでは相手のIPやポート番号は不明ですから、要求されても困りますね。
(2)は質問者さんの認識通り。受信のために必要、送信では不要です。

QSocketのSend関数でのCLOSEの検知 [Linux]

Linux環境でSocket(dm:PF_INET,type:SOCK_STREAM)を使用しての、
Client&ServerプログラムをCで作成しているのですが、
そこでのSend関数の使い方についてご助力ください。

Client&Serverプログラムは下記のような動きをします。

[Client]
ServerへConnectした後、複数のDataを数秒間隔でServerへ
送信(send関数使用)します。受信(recvやread関数等)は、
一切行いません。

[Server]
ClientからのConnectを受け付けた後、Clientから受信(recv関数
使用)したDataを標準出力へ表示する。送信(sendやwrite関数
等)は、一切行いません。


さて、ここでもしClientプログラムがCloseを発行したり、マシン
DOWN等の理由でConnectionが切断され、Server側のSocketが
CLOSE_WAIT状態になった場合、Bufferに溜まっていたDataを
すべて受けきった後、recv関数が0を返してくれるので
相手が終了したことがわかります。

ここからが質問のMainです。

では、もしServerプログラムがCloseを発行したり、マシン
DOWN等の理由でConnectionが切断され、Client側のSocketが
CLOSE_WAIT状態になっても、CLOSE_WAIT直後のsend関数が
なぜか正常に処理されてしまいます。無論このDataは、
Server側は受け取りません。この次のsend関数実行時に
EPIPEが返ってくるので、ここでようやくSocketが切断された
ことが判ります。

これを何とかCLOSE_WAIT状態になった直後から、send関数で
切断を検知できるようにできないでしょうか。

よろしくお願いします。

以上

Linux環境でSocket(dm:PF_INET,type:SOCK_STREAM)を使用しての、
Client&ServerプログラムをCで作成しているのですが、
そこでのSend関数の使い方についてご助力ください。

Client&Serverプログラムは下記のような動きをします。

[Client]
ServerへConnectした後、複数のDataを数秒間隔でServerへ
送信(send関数使用)します。受信(recvやread関数等)は、
一切行いません。

[Server]
ClientからのConnectを受け付けた後、Clientから受信(recv関数
使用)したDataを標準出力へ表示する。送信(se...続きを読む

Aベストアンサー

#3です。
>完全な保証ではないのですが、”送れた/送れない”をきちんと
ログとして残す必要があるのです。

なるほど、そういう事情でしたか。それだと、それなりの信憑性が要求されますね。

>それと最初にご提案いただいたrecvをNonBlockモードで呼び出す
方法ですが、これだとrecvのリターン値は0が返ってこないでしょうか?

Linuxで以下のような、プログラムを組んで確認しました。

//送信前に、ノンブロッキングでrecvする。
ret = recv(sock,rbuf,sizeof(rbuf),MSG_DONTWAIT);
if (ret == -1 && errno == EAGAIN){
//正常なので送信可能
ret = send(sock,msg[i],sendlen,0);
if (ret != sendlen){
//送信エラーの処理
}
}else{
//切断検知時の処理
 // CLOSE_WAITになると ret=0が返る
}

サーバー側で切断時、直ちにrecvで戻り値=0となり、エラーの検知ができました。ret==-1 かつ errno==EAGAIN
であれば、回線は正常状態です。

#3です。
>完全な保証ではないのですが、”送れた/送れない”をきちんと
ログとして残す必要があるのです。

なるほど、そういう事情でしたか。それだと、それなりの信憑性が要求されますね。

>それと最初にご提案いただいたrecvをNonBlockモードで呼び出す
方法ですが、これだとrecvのリターン値は0が返ってこないでしょうか?

Linuxで以下のような、プログラムを組んで確認しました。

//送信前に、ノンブロッキングでrecvする。
ret = recv(sock,rbuf,sizeof(rbuf),MSG_DONTWAIT);
if (ret == -...続きを読む

Qsocket: recvはいつ,どれだけ受け取るのか?

 現在,参考書にしたがってC++でソケットプログラミングを書いています.

 sendとrecvを非同期にするために,本では select関数やWSAAsyncSelect関数などを利用していて,実際,本のとおりに書いて上手く動いています.

 ここで伺いたいのですが,recvは,どうやって「データが届いたか」を知るのでしょうか.

 同期ならば,トランシーバでの会話のように送信側が「どうぞ」といって送受信を交代させることができますが,非同期ならばそれができません.

 NICとかが,プログラムに「届いたぞ!( or これから届くぞ!)」と教えてくれるのでしょうか.あるいは逆に,プログラムがNICに「届いてる?」と聞いているのでしょうか.仮に,ここに書いたような方法で届いたことが分かったとしても,どれくらい受け取ればいいかは分かりません(それも併せて教えてもらっているのでしょうか.データを送るときには,どれだけ送ればいいか分かりますよね.受信するときはどうしてるのかを知りたいと思っています).

Aベストアンサー

Linux しか知らないので Linux で説明をします。

NIC が通信パケットを受け取ると割り込みが発生し、CPU は割り込みを受け付けて、対応するデバイスドライバを起動します。この時、ドライバはソケットバッファと呼ばれる構造体にパケットの中身をコピーして、Linux カーネルの本体に渡し、そこで TCP 等の上位プロトコル処理が行われます。

一方、ユーザプログラムの方は、 select() なり read() で待っている訳ですが、OS はもちろんプロセスが何を待っているかを知っているので、対応する待ちの条件が満たされると、この場合は select() や read() が、抜けてくる(return する)訳です。

という事で、ユーザのプログラムは select() なり read() なりで受信データを「待つ」ことが必要です。もちろん select() や read() が呼ばれた時点で既に受信しているのならば、それらは直ぐに帰ってきます。read() や recv() はデータが届いた事を知る、というよりは、届いているかチェックして、まだ届いていなければ届くまで待つ(read() が抜けてこない)という処理になります。また NIC とユーザプログラムが直接やり取りをするのではなく、間にバッファがあって、対応するソケットのデータがある(受信済み)/ないか(未受信)、という問い合わせを行っているだけです。

ソケットの場合、データの送受信は非同期であり、送受信のタイミングのずれは(ソケット)バッファである程度吸収されます。もちろん、送受信バッファが満杯になった場合は流量制御が働いて、結果的に送信側の write() や send() が待ちに入ることになります。

Linux (Unix) のソケットの受信では、read() 等で指定されたバッファが常に満杯で返されるとは限らない設計になっています。つまり、その時に受信しているデータを返すだけなので、read() で返されたバイト数を必ず見ないと間違った動きになるので注意してください。

Linux しか知らないので Linux で説明をします。

NIC が通信パケットを受け取ると割り込みが発生し、CPU は割り込みを受け付けて、対応するデバイスドライバを起動します。この時、ドライバはソケットバッファと呼ばれる構造体にパケットの中身をコピーして、Linux カーネルの本体に渡し、そこで TCP 等の上位プロトコル処理が行われます。

一方、ユーザプログラムの方は、 select() なり read() で待っている訳ですが、OS はもちろんプロセスが何を待っているかを知っているので、対応する待ちの条件が満...続きを読む

Qエクセルで分から時間に変換したいのですが

いつもお世話になっています。よろしくお願いいたします。
エクセルで「分」の合計を「時分」に変換して表示したいのですがどうもうまくいきません。
どなたかご教授願えないでしょうか?
例:200(分)=3時間20分もしくは3:20
お願いいたします。

Aベストアンサー

A1に「分」が入っていて、別のセルに時分に変換して表示する場合とします。

24時間(1440分)未満であれば、
=A1/1440
とし、セルの書式設定で以下のいづれかを設定すればOK。
(1)[時刻]→[13:30]を選択
(2)[ユーザー定義]→h:m
(3)[ユーザー定義]→h時間m分
※分単位は常に2桁(2時間05分など)で表示したいなら
 (1)の設定か、またはmをmmに変更してください。


上記方法では23時間59分までしか正しく表示できないので、
もし24時間(1440分)以上になる場合は別の方法が必要です。
=INT(A1/60)&":"&MOD(A1,60)
または
=INT(A1/60)&"時間"&MOD(A1,60)&"分"
※分表示を常に2桁にするのであれば、
 MOD(A1,60)をRIGHT("0"&MOD(A3,60),2)に変更してください。

Qシンボルが見つかりませんというエラーが理解できません。

以下のようなじゃんけんゲームのプログラムを書いたのですが、「シンボルが見つかりません。」というエラーが表示されるのですが、エラーの意味が理解できず、解決できません。どこが間違っているのか教えていただけませんか。

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

public class janken extends Applet
implements Runnable, ActionListener {
private static final int EXTERNAL_BUFFER_SIZE = 128000;

Image image[] = new Image[3];
Thread t;
int index1 = 0;
int index2 = 0;
String msg = "";
String msg1 = "";

boolean state = false;
Button b1 = new Button("ぐー");
Button b2 = new Button("ちょき");
Button b3 = new Button("ぱー");

public void init(){
for(int i = 0; i<=2; i++){
img[i] = getImage(getDocumentBase(),"hanabi" + (i+1) + ".JPG");
}
add(b1);
add(b2);
add(b3);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
msg1 = "結果は・・";

}

public void paint(Graphics g){
g.drawImage(img[index1],350,30,this);
g.drawImage(img[index2],695,30,this);
g.drawString("コンピューター",420,300);
g.drawString("あなた",800,300);
g.drawString(msg,630,320);
g.drawString(msg1,550,320);
}

public void start(){
state = true;
t = new Thread(this);
t.start();

}

public void run(){
while(state){
index1++;
if(index1 == 3){
index1 = 0;
}
index2++;
if(index2 == 3){
index2 = 0;
}
repaint();
try {
Thread.sleep(60);
}catch(InterruptedException e) { }
}
}

public void actionPerformed(ActionEvent e){
if(state == false) {
start();
return;

}
state = false;
if(e.getSource() == b1) {
msg = "ぐー";
index2 = 0;
}

else if(e.getSource() == b2){
msg = "ちょき";
index2 = 1;
}

else if(e.getSource() == b3){
msg = "ぱー";
index2 = 2;
}
check();
repaint();
}

public void check() {
if(index1 == index2) msg ="あいこ";


else if (index1 == 0) {
if(index2 == 2) msg="あなたの勝ち";
else msg ="あなたの負け";
}

else if(index1 == 1) {
if(index2 == 0) msg="あなたの勝ち";
else msg="あなたの負け";
}

else if(index1 == 2) {
if(index2 == 1) msg="あなたの勝ち";
else msg="あなたの負け";
}

}
}

以下のようなじゃんけんゲームのプログラムを書いたのですが、「シンボルが見つかりません。」というエラーが表示されるのですが、エラーの意味が理解できず、解決できません。どこが間違っているのか教えていただけませんか。

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

public class janken extends Applet
implements Runnable, ActionListener {
private static final int EXTERNAL_BUFFER_SIZE = 128000;

Image image[] = new Imag...続きを読む

Aベストアンサー

「シンボルを見つけられません。」というエラーの下に何か表示がありませんでしたか?そこにヒントがあると考えられます。
シンボルを見つけられませんといエラーが表示される主な理由は4つあります。
(1)クラス、メソッド、変数などの綴りミスや定義していない変数を使用している可能性がある。
(2)コンストラクタを呼び出すときに、newを忘れている可能性がある。(3)公開されていないメンバーを呼び出している可能性がある。
(4)必要なimport文を記述し忘れている可能性がある。
ここでのあなたのエラーは(1)番ではないでしょうか?上記ではimageとなっている変数がimgになっていますね。
これはエラー表示をよく見ることで意外と簡単に解決できるのです。
ゆっくり丁寧にエラー表示を見るように心がけることが大事ですよ。

QUTF-8とASCIIコードにおける互換性について

UTF-8とASCIIはそのASCIIコードの範囲のおいて
互換性を持ちます。(と、書籍や多種な文献にはそういった記述があります)

たとえば【A】という文字をUTF-8で符号化した際は【41】(16進数で)
さらにASCIIコードでも【41】という値がAという文字に割り当てられています。
確かに、一件互換しているようにみえますが、UTF-8っていうことは最終的には
Unicode上のコードポイントの値・・・つまり0x0041という値に復元?(というのでしょうか)するわけですよね?
でそのUnicodeの文字集合上から復元したコードポイントに対応する文字を参照しAという文字をみつけてくると・・・。
これって【A】という文字をUTF-8で符号化した歳のバイト列はASCIIと一致しているけれど
結局Unicodeコードポイントに直した場合【00】という上位バイトが無駄にくっついてきて【0x0041】となり
互換性がなくなるのではとおもったのですが・・・。

これはどういう意味の互換性なのでしょうか?
識者の方ご教授ください。
お願い致します。

Aベストアンサー

No1,3,6です。

>とあった時、おそらくどの言語でもそうだと思うのですが、スクリプトファイル内の特定の文字列はそれぞれ個別にエンコーディング情報を持つと思います。(※言語によっては持たいない?)

持たないのが普通です。
文字列個別にエンコード情報を持つのは、メジャーな言語だとRubyくらい?
他の言語では、プログラム中では1つのプログラム中では一種類のエンコードしか扱えません。もしくは、言語は全くエンコードを関知せず、すべてプログラマが管理するか。

最初の疑問に戻って、
「UTF-8とASCIIはそのASCIIコードの範囲において互換性を持ちます。」
というのは、
「ASCIIコードの範囲の文字を、ASCIIでエンコードしても、UTF-8でエンコードしても、全く同じ値になる」という意味であり、それ以上でも以下でも無いです。
別の言い方をすると、ASCIIコードの範囲の文字しか含まれないファイルであれば、そのファイルのエンコードがASCIIだとかUTF-8だとか、さらに(バックすらスラッシュ等)一部の記号を除けばSHIFT_JISだとかeuc-jpだとかいうのも区別できないというか同じです。

No1,3,6です。

>とあった時、おそらくどの言語でもそうだと思うのですが、スクリプトファイル内の特定の文字列はそれぞれ個別にエンコーディング情報を持つと思います。(※言語によっては持たいない?)

持たないのが普通です。
文字列個別にエンコード情報を持つのは、メジャーな言語だとRubyくらい?
他の言語では、プログラム中では1つのプログラム中では一種類のエンコードしか扱えません。もしくは、言語は全くエンコードを関知せず、すべてプログラマが管理するか。

最初の疑問に戻って、
「UTF-8とASC...続きを読む


人気Q&Aランキング