4

select を使用すると、ブロックせずに送受信できるバイトがあるかどうかを判断できます。

この関数を使用すると、受信できるバイト数を判断できます。

function BytesAvailable(S: TSocket): Integer;
begin
  if ioctlsocket(S, FIONREAD, Result) = SOCKET_ERROR then
    Result := -1;
end;

また、送信できるバイト数を特定する方法はありますか?

したがって、Nバイトでsendを呼び出すと、送信されたNバイト(またはSOCKET_ERROR)が正確に返されますが、それ以下ではありません(送信バッファがいっぱいです)。

FIONWRITE は Winsock では使用できません。

4

2 に答える 2

4

MVP のアレクサンダー ニコロフ氏によると、Windows にはそのような機能はありません。彼はまた、「良いソケット コード」は FIONWRITE のような ioctl を使用していないと述べていますが、その理由については説明していません。

この問題を回避するには、関心のあるソケットで非ブロック I/O を有効にすることができます (おそらく を使用FIONBIO)。そうすれば、WSASendブロックせずに送信を完了できる場合はそのようなソケットで成功するかWSAGetLastError() == WSAEWOULDBLOCK、バッファが次の場合に失敗します。がいっぱいです ( のドキュメントにWSASend記載されているとおり):

WSAEWOULDBLOCK

ソケットの重複: 未解決の重複した I/O 要求が多すぎます。非オーバーラップ ソケット: ソケットは非ブロックとしてマークされており、送信操作をすぐに完了できません。

また、このエラー コードに関する注意事項もお読みください。

于 2012-12-26T15:43:05.477 に答える
0

Winsock send()は、ソケットがブロッキングモードで実行されており、ソケットのアウトバウンドバッファがキューに入れられたデータでいっぱいになった場合にのみブロックします。同じスレッドで複数のソケットを管理している場合は、ブロッキングモードを使用しないでください。1つのレシーバーがタイムリーにデータを読み取らない場合、そのスレッドのすべての接続が影響を受ける可能性があります。代わりに非ブロッキングモードを使用してください。そうすると、send()は、ソケットがブロッキングが発生する状態になったことを報告します。次に、select()を使用して、ソケットが新しいデータを再び受け入れることができる時期を検出できます。より良いオプションは、代わりにオーバーラップしたI/OまたはI/O完了ポートを使用することです。アウトバウンドデータをOSに送信し、OSに待機中のすべてを処理させ、データが最終的に受け入れ/送信されたときに通知します。その通知を受け取るまで、特定のソケットの新しいデータを送信しないでください。

于 2012-12-29T02:12:11.170 に答える