ネットワークプログラミング-read()/write()/assert()関数


序文
TCPベースのネットワークプログラミングではread/recvを用いてデータを受信し,write/sendを用いてデータを送信する.sendto/recvfromはTCPデータ伝送にも使用可能
1.read関数
  • [1]ヘッダファイル
  • unistd.h

  • [2]関数プロトタイプ
  • ssize_t read(int fd, void *buf, size_t count);
  • 機能:記述子fdが指すファイルからcount文字をbufが指すキャッシュ領域の
  • に読み出す.
  • パラメータ:
  • fd:ファイル記述子
  • buf:読み出しデータを格納アドレス
  • count:読み込む文字

  • [3]関数の戻り値:いくつかの状況に分ける
  • 1)通常ファイルからのreadデータ
  • 成功:読み出されたバイト数
  • を返す
  • ファイルの末尾またはデータなしで読み取り可能:0
  • を返します.
  • エラー:-1
  • を返します.
  • 指定バイト数を読む前にファイルの末尾まで読む場合、例えば、ファイルの末尾までに30バイトがあり、100バイトを読む必要がある場合、readは30を返し、次にreadを呼び出すと、0(ファイルの末尾)
  • を返す.
  • 2)デバイスファイルからのreadデータ
  • 端末という装置では、通常1行ずつ読み、改行まで読むと
  • を返す.
  • がreadを呼び出すと、端末が改行文字を入力するまで待機し、残りのデータはカーネル端末装置バッファ
  • に保存される.
  • 3)readソケット用
  • 相手が接続を終了すると0
  • に戻る.
  • 読み出し中に信号が中断する:一部のデータを読み出した場合は読み出したデータを返し、読み出しがない場合は-1、errnoはEINTR
  • である.

  • [4]補足:socket readのブロックと非ブロック
  • ブロックsocket:readは、データが戻ってくるのを待つことをブロックし続け、データ量にかかわらず実際に読み取った文字数
  • を返す.
  • 非ブロックsocket:socket受信バッファにデータがあるかどうかにかかわらずすぐに戻り、実際に読み取った文字長を返すデータがあり、データ戻り-1がなく、errnoはEWOULDBLOCKまたはEAGAIN(ブロックに設定すべきことを示す)
  • である.

    2.write関数
  • [1]ヘッダファイル
  • unistd.h

  • [2]関数プロトタイプ
  • ssize_t write(int fd, void *buf, size_t length);
  • 機能:bufが指すバッファから記述子fdが指すファイルにlengthバイトを書き込む
  • .
  • [3]関数の戻り値:
  • 成功:書き込み文字数
  • を返します.
  • 失敗:-1
  • を返します.
  • ブロックおよび非ブロック戻り値:
  • ブロック:readとは異なり(実際に読み取った文字数を返す)、writeはバッファがbuffer全体を置くのに十分な場合にのみ
  • を返す.
  • 非ブロック:ドロップ可能なバイト数を返し、その後呼び出しは-1を返し、errno=EAGAINまたはEWOULDBLOCK
  • を返す.


    3.送信および受信バッファ&&read/write呼び出しブロック
  • write成功
  • writeは正常に返されたが、bufのデータがkernelのTCP送信バッファにコピーされただけである.データがいつネットワークに送信されるか、いつ相手のホストに受信されるか、いつ相手のプロセスに読み込まれるかについては、システム呼び出しレベルでは保証や通知は与えられません.
  • 送信側および受信側キャッシュ
  • は、TCPまたはUDP
  • にかかわらず、socketごとに独自の送信および受信バッファを有する.
  • send buffer:ネットワークに送信されたデータは依然としてsend bufferに一時保存する必要があり、相手のackを受信した後、kernelはbufferからこのデータの一部を消去し、後続の送信データのために空間
  • を空ける.
  • receive buffer:受信側は受信したデータをreceive bufferに一時保存し、自動的に確認する.しかし、socketが存在するプロセスが直ちにreceive bufferからデータを取り出すことができなければ、最終的にreceive bufferが満たされ、TCPのスライドウィンドウと混雑制御のため、受信側は送信側がその送信データ
  • を阻止する.
  • writeおよびread呼び出しブロック
  • write呼び出しブロック:一般的に、受信側プロセスがsocketからデータを読み出す速度が送信側プロセスがsocketにデータを書き込む速度に追いつかないため、最終的に送信側write呼び出しブロック
  • を招く.
  • read呼び出しブロック:socketのreceive bufferからアプリケーションのbufferにデータをコピーし、read呼び出しブロックは、通常、送信側のデータが
  • に達していない.

    4.assert()関数
  • [1]ヘッダファイル
  • assert.h

  • [2]実装
  • C標準ライブラリでは、assertは関数
  • ではなくマクロで実現される.
  • 式:int assert(int expression);
  • 機能:式expressionを先に計算し、値が0の場合、stderrにエラー情報を印刷し、abort()を呼び出して
  • の実行を終了します.
  • [3]用法まとめ
  • 関数の開始時に入力パラメータの妥当性を検証する
  • int resetBufferSize(int nNewSize)
    {
      assert(nNewSize >= 0);
      assert(nNewSize <= MAX_BUFFER_SIZE);
      ...
    }
  • は一度に1つの条件のみを検証し、複数を検証すると、断言失敗はどの条件エラー
  • であるかを直観的に判断できない.
  • 環境を変更する文
    assert(i++ < 100)
       i    100, ++
    を使用できないエラー、例えばiが実行される前に100である場合、i++というコマンドは
  • を実行しない.
  • [4]assertの欠点と回避
  • 頻繁に呼び出すと、プログラムのパフォーマンスに大きく影響し、追加のオーバーヘッド
  • が増加します.
  • 回避:デバッグが終了した後、assert.hヘッダファイルの前に#define NDEBUGを追加してassert呼び出しを禁止する
  • #include 
    
    #define NDEBUG
    #include 

    参考記事:
    http://www.cnblogs.com/xiehongfeng100/p/4619451.html
    http://www.cnblogs.com/Dscxy/p/4103833.html
    http://www.cnblogs.com/ggzss/archive/2011/08/18/2145017.html
    2017.11.03