Armadilloフォーラム

send()エラーならない現象

ma2013

2016年4月7日 16時12分

いつもお世話になっております。
MCSのマーと申します。

最近, armadilloIoT G2で TCPクライアントを実装してみたが,
下記課題がありまして,解決案はありませんでした。
どなたかご存知な方いればお願いいたします。

クライアントはTCPサーバとコネクションを確定後(3G),
3Gネットワークインターフェースをifdownで無効にしても,
クライアントのsend関数はエラーを戻さない現象です。
サーバ側は受信しないようになった。
EPIPEエラーにならないのはちょっと不思議でした。

コメント

saitoh

2016年4月8日 15時46分

齊藤と申します。
誰も応答しないので一般論で答えます。

sendだとカーネル内バッファにコピーしただけで
リターンする(場合があるのではないでしょうか)。

何かパケットを送信しようと試みるまではデータリンク層切断という
事実はトランスポート層に伝わらないので、(すぐには)エラーにならないのでしょう。

izawa

2016年4月8日 16時19分

伊澤@ITTOです。私も一般論で。
ソケットプログラミングをするならここは読んでおくと捗りますよ。
http://www.kt.rim.or.jp/~ksk/sock-faq/unix-socket-faq-ja.html#toc2
件の現象はこれでしょう。
>相手側が (SO_LINGER を使ったややこしいことをしないで) close() するか終了したとすると、
>write() 呼び出しで何が 起こるかは、もうちょっとわかりづらいです。直後の呼び出し時ではな く、その次の呼び出し時にEPIPE が返るでしょう。
理由は齊藤さんの書いた通りでよさそうです。

ma2013

2016年4月8日 17時23分

MCSのマーです。

皆様から色々アドバスをいただきまして,本当にありがとうございました。
TCP SOCKETの場合でも,確実に相手にデータを送信するのはなかなか難しそうですね。
何かその他アドバスがございますと是非お願いいたします。

y.nakamura

2016年4月8日 18時36分

中村です。

> TCP SOCKETの場合でも,確実に相手にデータを送信するのはなかなか難しそうですね。
> 何かその他アドバスがございますと是非お願いいたします。

はっきりしたことが言えないので様子見だったのですが、
私からも少し。

VMwarePlayerで動かしているCentOSのeth0で試してみました。
establishedになっいるTCP接続がある状態で、
ifconfigでeth0をdownしたあともnetstatでの表示は
establishedのままでした。

establishedなので、downしたあとしばらくの間は、
送信側はカーネルの送信バッファにデータを詰め込んで
いける状態になっているのではないでしょうか?

UDPでなくTCPとはいえ、send()で(たぶんwrite()も)
ほんとに送信ができたかどうかを判断するには、
アプリレベルで何か応答を待って、それを確認するようなことを
するしかないのかな?と思ってます。

--
なかむら

saitoh

2016年4月9日 9時44分

齊藤です
「確実にデータを送信する」というのが何を意味するのか不明確なのですが、,,。
問題の状況でも、close()したらエラーが帰ってきてデータがちゃんと送達されなかった
ことは分かるはず。

セッションをcloseせずにネット切断を検知したいのなら、KEEPALIVEをつかう
とか、バッファに溜まった(かもしれない)データを強制的に送出するか・・・

当初の投稿であげられたシチュエーションでもそのまましばらく(200msかな)まてば
バッファの送信が行なわれてエラーになって、もしクライアントが
read()で待ってればread()がエラーで帰るのではないかと想像します。