0

したがって、TCP でパケットを送信する次のコードがあります。それはかなりうまくいっています。部分的な書き込みをテストするだけです。そのため、sendbuf を 1 に設定するか、以下に示すようにハックを実行して、一度に 1 バイトを書き込みます。tcpdump を取得したとき、最初のバイト以外はすべて正しくありませんでした..何が間違っているのでしょうか?

int tmi_transmit_packet(struct tmi_msg_pdu *tmi_pkt, int len, int *written_len)
{
int bytes;

// This works
bytes = write(g_tmi_mgr->tmi_conn_fd, (void*) tmi_pkt, len); 

// This doesn't: 
// bytes = write(g_tmi_mgr->tmi_conn_fd, (void*) tmi_pkt, 1); 

if (bytes < 0) {
    if (errno == EAGAIN) {
        return (TMI_SOCK_FULL);
    }
    return (TMI_WRITE_FAILED);
} else if (bytes < len) {
    *written_len += bytes;
    tmi_pkt += bytes;
    return (tmi_transmit_packet(tmi_pkt, len - bytes, written_len));
} else {
    *written_len += len;
}
return TMI_SUCCESS;
}
4

1 に答える 1

2

この行

tmi_pkt += bytes;

ほとんどの場合、期待どおりに動作しません。

だけではなく、 だけ増加しtmi_pktます。ポインター演算のわかりやすい説明については、ここをクリックして binky を参照してくださいsizeof(*tmp_pkt) * bytesbytes

これを回避するには、次のようにコードを変更します。

...
else if (bytes < len) {
  void * pv = ((char *) tmp_pkt) + bytes;
  *written_len += bytes;
  return (tmi_transmit_packet(pv, len - bytes, written_len));
}
...

いずれにせよ、書き込み関数に渡されたポインタが指すデータは必ずしもその型に対応する必要がないため、これはどういうわけか汚い匂いがします。

したがって、よりクリーンな解決策は、使用しないでstruct tmi_msg_pdu *tmi_pktvoid *またはchar *関数パラメーター宣言として使用することです。

静かで贅沢ですが、ここでの再帰呼び出しの使用は必要ではなく、推奨もされていません。大量のデータや低速の転送では、スタック メモリが不足する可能性があります。単純なループでも構いません。後者には、書き込まれるバッファーへの一時ポインターを使用でき、型付きインターフェイスに固執できるという利点があります。

于 2013-03-15T07:23:35.863 に答える