(C言語)Linuxのpacket socket(socket(AF?PACKET, SOCK_DGRAM, htons(ETH_P_IP))) を使ってTCPの3way handshakeをOSのプロトコルスタックに頼らず自力で挑戦しています。
RFCやほかの技術本をよんでIPヘッダやTCPヘッダの実装は一応できたのですが、肝心のsynパケットを送った後のackパケットが返ってきません。
wiresharkでは問題なくsynパケットと認識できているのですが、きっとどこかに不備があるはずです。
そこでC, C++ Javaでもいいのでこのプログラムの実装例が載っているサイトなどを教えてください。(英語でもかまいません)

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

A 回答 (4件)

> ところで、jjk65536さんはこういった情報をどこから入手しているのですか。


> raw socketやpacket socketを解説してくれているサイトはかなり少ないように感じます。
> 掲示板やこういった質問サイトも普段から利用されているのでしょうか。

基本的にはGoogle検索で調べてますね。
自分の英語読解力があてにならないので、基本的には海外のサンプルコードを
自分で動かして見ながら期待動作するように作ったりしてます。

教えてGoo!では普段C言語あたりを見たり回答したりしてます。

ちなみに、パケットキャプチャ中にだれかがSynをだしてたんですよ。
それにはRstの応答が返ってるんですね。
試しにそれと同じパケットを自分で出してみたんですが、Rst応答が
来なかったんです。
なんなんでしょうね。セキュリティ上の理由で同じパケットが来ても
Rst応答はしない、とかあるかもしれません。

気になる内容なので、詳しい方が現れてズバっと解決してくれると僕も嬉しいんですが。

この回答への補足

>> ちなみに、パケットキャプチャ中にだれかがSynをだしてたんですよ。
それにはRstの応答が返ってるんですね。
試しにそれと同じパケットを自分で出してみたんですが、Rst応答が
来なかったんです。

なぜだかさっぱりです。僕の作ったパケットが悪いと思っていたのですが、原因はそれだけではないのかもしれませんね。
LinuxやBSDあたりのプロトコルスタックの実装をソースコードを読んで理解できればいいのですが... ちょっとハードルが高いです。

本当にズバッと解決できたらいいのですが。

補足日時:2011/04/15 02:54
    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2011/04/17 23:15

> だとしたら`TCP header length(24bytes)` / 4 = 6であっているのではないでしょうか。



すんません、合ってましたね。
普段Wiresharkの解析に頼りっきりで、ちゃんと自分で読んでなかったから
そんなことも忘れてました。

さて、提示して頂いたバイナリをパケットにして手元のPCで出力してみましたが、
やっぱりRstも来ないですねぇ。

他に詳しい方が現れるかとも思っていたんですが、いらっしゃらないみたいですね…。
力及ばず申し訳ないです。

ところでSOCK_RAWって生ソケットですよね?
これでTCPヘッダの大半をOSが作ってくれるとは初耳です。
どこのサイトに解説があったのか、教えて頂けませんか?

私は普段SOCK_RAWをEtherフレームからCで構築するときに使ってるんですが…

この回答への補足

>> ところでSOCK_RAWって生ソケットですよね? これでTCPヘッダの大半をOSが作ってくれるとは初耳です。どこのサイトに解説があったのか、教えて頂けませんか?

すみません、大嘘でした。
ハードディスクの片隅から探し出したところ0のダミーで埋めてあっただけで一応TCPヘッダは作っていました。そのときのソケットはsocket(AF_INET, SOCK_RAW, IPPROTO_TCP)でした。
どこのサイトにあったかは覚えていません。たぶん海外のサイトだったと思います。
packet socketは自分で作ったヘッダはkernelによって書きかえられませんが、RAW SOCKETはソースIPやチェックサム等はkernelによって書き換えられるので勘違いしていました。
(まぁ、考えようによってはkernelが作ってくれているともいえなくもありませんが)

ところで、jjk65536さんはこういった情報をどこから入手しているのですか。
raw socketやpacket socketを解説してくれているサイトはかなり少ないように感じます。
掲示板やこういった質問サイトも普段から利用されているのでしょうか。

補足日時:2011/04/13 20:18
    • good
    • 0

見ました。


TCPヘッダ内のヘッダレングスが96バイトって間違ってません?
24バイトくらいになるかと思いますが。

以下のように通信しようとしていると読めましたが、合ってますか?
tcp/ip src=127.0.0.1:14818 dst=127.0.0.1:61256

そうであれば、そのPCの61256番ポートでは何かのデーモンがListen
していますか?
例えば、パケットキャプチャ中にターミナルで
# telnet 127.0.0.1 61256
としたときに、期待したAck(またはRst)は観測できますか?

目で追っていったので、読み間違いがあるかもしれません。
指摘が間違ってたらすんません。

この回答への補足

>> 以下のように通信しようとしていると読めましたが、合ってますか?

はい、あっています。


>> TCPヘッダ内のヘッダレングスが96バイトって間違ってません?


"TCPヘッダ内のヘッダレングス"というのはTCPヘッダの12バイト目から4ビット間のRFCでいうところの"Data offset"のことですか?
だとしたら`TCP header length(24bytes)` / 4 = 6であっているのではないでしょうか。
間違っていたらすみません。(そのときはTCPヘッダのどの部分かご教授お願いします)
一応wiresharkと自作のパケットキャプチャーソフトではTCP header lengthは24byteとでていますが...


いつもはLAN内のほかのPCで実験していますが、今回は自身に送りました。


>> そうであれば、そのPCの61256番ポートでは何かのデーモンがListenしていますか?

送信ポートは乱数で決めています。61256ポートで待機しているのはbind, listen, acceptでブロッキングしている自前のサーバプログラムではだめですか?

またtelnetで自前のプログラムにconnect()したときはwiresharkとtcpdumpで3way handshakeが正常に動作していることを確認しました。自前プログラムがポートでlistenしていない場合はrstが帰ってくることも確認しました。

前にどこかのWebページでみたAF_INET, SOCK_RAWをつかったプログラムは今回と同じ環境できちんと動作しましたが、この場合TCPヘッダのControl Bitsを除くIPヘッダ全体とTCPヘッダの大半はOSが作ってくれていたので、今回はEthernet headerを除くすべてのヘッダを自前で作りたいです。



よろしくお願いします。

補足日時:2011/04/12 21:40
    • good
    • 0

OpenSouceでしたら、LinuxよりBSDのネットワークスタックが読みやすいと


詳しい人に聞いたことがあります。(自分ではまだ読んでません、すんません)

それよりも、送信したSynパケットのダンプデータでも貼ってみてはいかがでしょう?
スクリーンキャプチャを撮って画像添付するとか。
わかる方が間違いを指摘してくれると思いますよ。私も見ます。

また、対向のサーバはそのSynパケットに対して正しくAckを返せるように
調整されているのでしょうか?
そのポートはサーバでオープンされていますか?
そのポートをTCPでListenしているデーモンは可動していますか?
対向サーバ上のWiresharkでは、Synパケットは観測できていますか?

その辺がOKなら、やはりパケットのどこかに間違いがあるのだと思います。
見てみたいですね。

この回答への補足

ヘッダに設定したポートにサーバーを走らせてもうんともすんとも言わず、さらに普通listenしていないポートにsynパケットを送るとrstパケットが帰ってくるはずなのですが、それも帰ってきません。多分IPヘッダidやTCPヘッダのack numberあたりが怪しい。(完全に初心者)
絶対にどこかでとんちんかんなことになってるはずです。
以下wiresharkで確認したループバックに送ったsynパケットの16進ダンプ(MSS=1460のオプション付き)

(Ethernet header)00 11 11 94 7f 34 00 00 00 00 00 00 08 00
(ここからIP header)45 00 00 2c 70 ea 40 00 40 06 cb df 7f 00 00 01 7f 00 00 01
(ここからTCP header)39 e2 ef 48 00 03 1b 32 00 00 00 00 60 02 0c cf f6 c7 00 00 02 04 05 b4

補足日時:2011/04/11 18:13
    • good
    • 0

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

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

このQ&Aを見た人はこんなQ&Aも見ています

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

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

QTCPヘッダのチェックサム算出方法

TCPヘッダのチェックサム算出方法について
1.算出方法はIPヘッダと一緒か?

2.一緒なら
unsigned short CalcCheckSum(unsigned short*lpData,/* (in)チェックサム算出文字列の先頭アドレス */
intiDataLen)/* (in)チェックサム算出文字列長 */
{
unsigned longlCheckSum = 0;

while(iDataLen > 1)
{
lCheckSum += *lpData++;
iDataLen -= 2;
}

if(iDataLen)
{
lCheckSum += *(unsigned char *)lpData;
}

lCheckSum = (lCheckSum & 0xFFFF) + (lCheckSum >> 16);
lCheckSum = (lCheckSum & 0xFFFF) + (lCheckSum >> 16);

return((unsigned short)~lCheckSum);
}
でまちがいないか?

3.オプションが追加されるときはそこも算出対象になるのか?教えていただけないでしょうか?
よろしくお願いします。

TCPヘッダのチェックサム算出方法について
1.算出方法はIPヘッダと一緒か?

2.一緒なら
unsigned short CalcCheckSum(unsigned short*lpData,/* (in)チェックサム算出文字列の先頭アドレス */
intiDataLen)/* (in)チェックサム算出文字列長 */
{
unsigned longlCheckSum = 0;

while(iDataLen > 1)
{
lCheckSum += *lpData++;
iDataLen -= 2;
}

if(iDataLen)
{
lCheckSum += *(unsigned char *)lpData;
}

lCheckSum = (lCheckSum & 0xFFFF) + (lCheckSum >> 16);
lCheckSum = (lCheck...続きを読む

Aベストアンサー

これ参考になりませんか。

参考URL:http://www.f4.dion.ne.jp/~adem/rfc/rfc793.euc.txt

QwiresharkでパケットモニタするとRetransmissionが多発しているという意味は?

現在、自分で作成したパケット送信クライアントプログラムをテストしており、3秒に1回のタイミングでインターネット上にあるサーバのグローバルipアドレスに対し、TCPパケットを発信させて受信するというテストを行っています。
しかし、3秒に一回データを送っているはずなのに、その間隔10秒とか20秒とか間隔が開いてしまう時があります。

wiresharkというパケットモニタソフトで送信側、受信側共にパケットモニタを行ってみたところ、”Retransmission”が多発しているということがわかりました。(tcp.analysis.retransmissionというフィルタ設定で検索)この現象はある時とない時があります。テストして10日ぐらい経つのですが、このパケットが確認されるのはお昼の12時頃と夕方の6時頃が多いのですが、このことからどのようなことが起こっていると考えられますか?

わかる方いらっしゃいましたらご教授よろしくお願いいたします。

Aベストアンサー

簡単に言うと「トラフィック過多によるパケットの再送が多発している」です。

噛み砕いて言えば「回線が混雑していて、送信したパケットが、他の誰かが送信したパケットと衝突(コリジョンが発生)してパケットが消えた。なので、もう一度、送り直した」と言う事。

>このパケットが確認されるのはお昼の12時頃と夕方の6時頃が多いのですが、このことからどのようなことが起こっていると考えられますか?

「お昼休み、終業時間の6時になると、みんな、メールをチェックしたり、個人的にインターネットを閲覧し、トラフィック過多が起き、回線が異常に混雑する」と言う事が起きていると考えられます。

解消するには以下の方法があります。
・「休み時間も、終業時間後も、プライベートでネットを使うな!」と言う「通達」を全社に出す
・社内LANを、トラフィック過多によるコリジョンが起きないよう高速で帯域のあるネットワークカード、LANハブ、ルーターに変える
・受信側と送信側を、社内LANから(電気的、アドレス的に)独立した別のLANにする

要は「混んでる時間帯なので仕方が無い」って事です。

簡単に言うと「トラフィック過多によるパケットの再送が多発している」です。

噛み砕いて言えば「回線が混雑していて、送信したパケットが、他の誰かが送信したパケットと衝突(コリジョンが発生)してパケットが消えた。なので、もう一度、送り直した」と言う事。

>このパケットが確認されるのはお昼の12時頃と夕方の6時頃が多いのですが、このことからどのようなことが起こっていると考えられますか?

「お昼休み、終業時間の6時になると、みんな、メールをチェックしたり、個人的にインターネットを...続きを読む

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 はもちろんプロセスが何を待っているかを知っているので、対応する待ちの条件が満...続きを読む

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)は質問者さんの認識通り。受信のために必要、送信では不要です。

QLinuxでパケットを発信する際・・・。

ひとつ疑問なのですが、たとえばudpでパケットを送信するときに、sockaddr構造体を使って

dest_addr.sin_port = htons(10001);

などで送信先を定義しますよね。このとき、自分の発信元ポートは
決められないのでしょうか。

通信相手がマイコンでして、要求パケットを受けたら自分のステータスを
発信元にそのまま送り返すというシロモノで・・・発信元ポートがわからないと
サーバ側でlistenできないんです・・・。

パケットを拾ったところ、1045発10001着のようにランダムで決められているんですね。
なにかいいアイデアはありますでしょうか?

Aベストアンサー

少し時間が取れたので、私も試してみました。

a-kuma> ポート番号だけじゃなくて、相手先のIPアドレスもきちんと設定しましたよね?

何を言ってるんでしょうね。思い付きの方は良かったのに、頭の中が腐ってる
ようです (^^;

No.3 の Fooky さんも「さっきやった間違い」とあるので、私だけが特に そこつ者
なわけではないようですが、思い込みがあったので、ちょっとはまりました。

■送信側

int sock = socket(PF_INET, SOCK_DGRAM, 0);

sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(2500);  // このポートに返して欲しい
addr.sin_addr.s_addr = INADDR_ANY;
bind(sock, (sockaddr*)&addr, sizeof(sockaddr_in));

memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(1999);  // 送信の為のポート
memcpy(&addr.sin_addr.s_addr, gethostbyname("相手のホスト名")->h_addr_list[0], sizeof(addr.sin_addr.s_addr));

char* buf = "test message";
sendto(sock, buf, strlen(buf) + 1, 0, (sockaddr*)&addr, sizeof(sockaddr_in));


■受信側

int sock = socket(PF_INET, SOCK_DGRAM, 0);

sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(1999);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

bind(sock, (sockaddr*)&addr, sizeof(sockaddr_in));

char buf[256];
int len;
recvfrom(sock, buf, sizeof(buf), 0, (sockaddr*)&addr, &len);
cout << "port: " << htons(addr.sin_port) << endl;

少し時間が取れたので、私も試してみました。

a-kuma> ポート番号だけじゃなくて、相手先のIPアドレスもきちんと設定しましたよね?

何を言ってるんでしょうね。思い付きの方は良かったのに、頭の中が腐ってる
ようです (^^;

No.3 の Fooky さんも「さっきやった間違い」とあるので、私だけが特に そこつ者
なわけではないようですが、思い込みがあったので、ちょっとはまりました。

■送信側

int sock = socket(PF_INET, SOCK_DGRAM, 0);

sockaddr_in addr;
memset(&addr, 0, s...続きを読む

QWinsockの通信処理にてファイル転送方法?

環境:Windows2000とUNIXサーバ
開発:VisualStadioVer6.0
言語:C言語

やりたいこと:
   クライアントからサーバにファイル送信を行う。

ただし、FTP通信を使わないで、別ポートにて、Winsockの
send等でFTPもどきのファイル送信を行いたい。

ソケット通信はデータ送信なのは知っているのですが、
どうしても実現したいので、知ってる方は教えてください。

Aベストアンサー

普通にできますよ。
socket(),bind(),listen(),accept()
socket(),connect()
等で socket()をセットアップしたら
こんな感じでやるだけです。

int socket;
char buf[4096];
const char* filename;
FILE *file;
int num_read;

送るほう:
if( !(file = fopen(filename,"rb")) ) return;//error
while( num_read = fread(buf,sizeof(buf),1, file) )
if( write(socket,buf,num_read) < num_read )
return; //error
}
受け取るほう:
if( !(file = fopen(filename,"wb")) ) return;//error
while( num_read = read(socket,buf,sizeof(buf)) )
if( fwrite(buf,num_read,1,file) < num_read )
return; //error
}

普通にできますよ。
socket(),bind(),listen(),accept()
socket(),connect()
等で socket()をセットアップしたら
こんな感じでやるだけです。

int socket;
char buf[4096];
const char* filename;
FILE *file;
int num_read;

送るほう:
if( !(file = fopen(filename,"rb")) ) return;//error
while( num_read = fread(buf,sizeof(buf),1, file) )
if( write(socket,buf,num_read) < num_read )
return; //error
}
受け取るほう:
if( !(file = fopen(filename,"wb")) ) return;/...続きを読む

Qprintf による16進表示について

C言語初心者です。

今作っているプログラムで、データを16進形式で表示しようとしています。
大体このような感じです。

/*入力時*/
char buf[5]={0x4e,0x94,0xa0,0x2b,0x78}

/*出力時*/
for (i = 0; i < 5; i++) {
printf("0x%02x\n",buf[i])
}

実際には入力後にある処理によってbufは更新されるのですが、printfの出力結果として、

0xffffff4e
0x94
0xffffffa0
0x2b
0x78

というように、'ffffff'が付加したものがいくつか出力されてしまいます。
これはどういった意味を持つのでしょうか?

なんか初心者ならではの漠然とした質問ですいません。。。

Aベストアンサー

出力は、
0x4e
0xffffff94
0xffffffa0
0x2b
0x78
ではありませんか?
char が符号付(-128~127)のため、0x80~0xffは負の数とみなされます。printfの引数になる時に 符号付charは符号付intに変換されますが、このCコンパイラの場合は、int が4バイトcharが1バイトのため、上位3バイトに負の数を示すffffffが入ります。
char x=255;
printf("%d\n",x);
だと255でなく、-1が表示されます。

対応としては、
unsingned char buf[5]={0x4e,0x94,0xa0,0x2b,0x78}
;
とするか、
printf("0x%02x\n",buf[i]&0xff);
にするかどちらかですね。

Qセグメンテーション違反

C言語を使用しています。

構造体に値をいれようとしたら、コンパイルは出来るのですが、実行時に
「セグメンテーション違反です (core dumped)」
となってしまい、それ以上行えません。

構造体と代入したい変数との型は、合っています。

いろいろ本などで見ましたが、何が原因かわからず困っています。
教えてください。
宜しくお願いします。

Aベストアンサー

OSは何でしょうか。コンパイラは何を使用していますか?
通常、デバッグオプションをつけて実行すると、異常の発生したソースの箇所で止まりますので、それが手がかりになります。またNo1の方が言われてますように、ソースが公開できるのであれば、ソースを提示するのが良いかと思います。

Qソケット通信内 read関数について

現在C言語にソケット通信を作成しているのですが、read関数内の作成でつまずいています。
ご存知でしたら教えてください。

自分なりに調べた結果read関数の戻り値は受信した
バイト数、毎回指定サイズ受け取るとは限らないと
いうことでした。

そこでread関数を無限ループで回し
指定サイズ受信したら、ループを抜ける使用にしたのですが、受信バイトが0だった場合はどうすればよいのでしょか?
よくサンプルなどでは、0だったらエラーと判断し、すかさずbreakしているのですが、一度でも0バイトを受信すると、それ以降は1バイト以上受信出来ないものなのでしょうか?
もし出来ないのなら一度でも0を受信したら、breakしようと思っています。
出来るのでしたら、タイマー設定をし、指定受信バイトに満たなくても一定時間が過ぎたらループから抜ける使用にしたいと考えています。
そのほか良い方法があれば教えてください。

分かりずらい説明になってしまいましたが、宜しくお願い致します。

Aベストアンサー

selectの戻り値が1となったのならば一歩前進です。
あとは、FD_ISSET()して期待通りのソケット番号にデータきていれば受信できると思います。

ところで今回のソースでFD_SET()のところはどうなっていますか?
selectでいつも0となるのはFD_SETがちゃんとできていないような気がします。
前回と今回のソースで差分をチェックしてみてはどうでしょうか。

がんばってください!


あと、ほかに参考になりそうなページをのせてみます。
「selectを使う」の項目が役立ちそうです。fdという変数にaccept()した戻り値を入れるようにすればいけます。

参考URL:http://www.ops.dti.ne.jp/~allergy/socket/socket.html


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報