問題タブ [socketchannel]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - SocketChannel は isReadable() を起動しますが、読み取るものはありません
Android アプリで新たな問題が発生しました。はそれSocketChannel
を教えてくれますisReadable()
が、読むものは何もありません。
で必要な関数を呼び出しますonProgressUpdate
。WebSocket
アプリなのでハンドシェイクを送受信する必要があります。ハンドシェイクの送受信は、この while ループで動作します。最初にSelectionKey.isWriteable()
と ハンドシェイクが送信され、次にSelectionKey.isReadable()
と ハンドシェイクが読み取られます。しかし、それSelectionKey.isReadable()
はまだ真実です。ここで、通常の読み取り関数 ( ではないreadHandshake
) 関数が呼び出されます。しかし、読むべきものは何もありません。私の読み取り関数のコードは次のとおりです。
今度は、無限の while ループに陥ります。読み取るものがなく、bytesRead が 0 のままであるため、remainingBytes が < 0 になることはありません。
私の質問は、読むものが何もないのに isReadable が真なのはなぜですか?
java - Java NIO: 非ブロッキング I/O で SocketChannel read() がいつ完了するかを知る方法
現在、ノンブロッキング SocketChannel (Java 1.6) を使用して、Redis サーバーのクライアントとして機能しています。Redis はソケットを介してプレーンテキスト コマンドを直接受け入れ、CRLF で終了し、同様に応答します。簡単な例を次に示します。
送信: 'PING\r\n'
RECV: '+PONG\r\n'
Redis は、\r\n で終わるデータの多くのセクションをすべて単一の応答の一部として、(要求内容に応じて) 巨大な応答を返すこともできます。
標準のwhile(socket.read() > 0) {//append bytes}ループを使用して、ソケットからバイトを読み取り、クライアント側でそれらを再アセンブルして応答にします。
注: 私はセレクターを使用していません。サーバーに接続された複数のクライアント側 SocketChannel を使用して、送受信コマンドのサービスを待機しています。
私が混乱しているのは、ノンブロッキングモードでのSocketChannel.read()メソッドのコントラクトです。具体的には、サーバーが送信を完了し、メッセージ全体を取得したことを知る方法です。
戻りが速すぎてサーバーに返信する機会を与えるのを防ぐための方法がいくつかありますが、私が行き詰まっていることの1つは次のとおりです。
- read()がバイトを返し、その後の呼び出しでバイトを返さずに、別の後続の呼び出しで再びいくつかのバイトを返すことは可能ですか?
基本的に、少なくとも 1 バイトを受信し、最終的にread()が 0 を返す場合、サーバーが応答を完了したことを信頼できますか?それとも、サーバーがビジー状態で、一部を返した可能性がありますか?待って試行し続けると、さらにバイトが増えますか?
read() が 0 バイトを返した後でもバイトを送信し続けることができる場合(以前の読み取りが成功した後)、サーバーが私との通信をいつ終了したかを知る方法がわかりません。スタイル通信は、サーバーがいつ「完了」したかを知ることさえできます。
ご存じのように、接続が停止していて、これらが標準的な長寿命の DB 接続でない限り、read は -1 を返しません。したがって、リクエストごとに閉じたり開いたりすることはありません。
一般的な回答 (少なくともこれらの NIO の質問に対して) は、Grizzly、MINA、または Netty を調べることであることを知っています。可能であれば、サードパーティの依存関係を採用する前に、これらすべてが生の状態でどのように機能するかを本当に知りたいです。
ありがとうございました。
ボーナス質問:
私は当初、ブロッキング SocketChannel がこれを使用する方法になると考えていました。コマンドを処理して応答を返すまで、発信者に何もしてほしくないからです。
それがより良い方法であることが判明した場合、指定されたバッファーを満たすのに十分なバイトがない限り、SocketChannel.read() がブロックされるのを見て少し混乱しました...すべてをバイト単位で読み取ることはできませんこのデフォルトの動作が実際にどのように使用されるのかわかりません...サーバーから返される応答の正確なサイズがわからないため、SocketChannel.read() への呼び出しは常にタイムアウトになるまでブロックされます (その時点で、コンテンツがバッファに残っていることが最終的にわかります)。
ブロッキングメソッドは常に読み取り時にハングアップするため、ブロッキングメソッドを使用する正しい方法についてはよくわかりません。
java - CyclicBarrier に関係なく、1 つのスレッドの停止が早すぎる
次のコードが下品に見えるかもしれないという事実を認識していますが、私はこれらのことに慣れておらず、機能させるためにすべてを試しました..
問題: CyclicBarrier を (間違った方法で使用している可能性があります) 使用しているにもかかわらず、1 つ (常に同じように見えます) スレッドがすぐに停止し、ベクターを出力して、「着信接続」メッセージの 11 のうち 1 つが欠落したままになります. ループの最後の繰り返しで何かひどく間違っている可能性がありますが、正確に何が何かを見つけることができないようです..今、プログラムは最後の接続を処理するのを待ってループします。
明確にするために、使用されるファイルの形式を次に示します。
構成には、スレッドであるクライアントが使用するホスト名とポートが含まれており、入力ファイルの行は、「このクライアントがそのクライアントにメッセージを送信する」または「このクライアントが論理クロックを一定の値だけインクリメントする」ことを意味します。
1 M 2 (M はメッセージの送信を意味します)
2 M 3
3 M 4
2 L 7 (L は増分クロックを意味します)
2 M 1
...
127.0.0.1 9000
127.0.0.1 9001
127.0.0.1 9002
127.0.0.1 9003
...
java - SocketChannel 接続に関する Java の問題
これはクラスの課題なので、答えよりもヒントが必要です。
4 つの仮想 Linux マシンでプロセスを実行しています。各プロセスは、隣接する 2 つのプロセスと通信します。各プロセスは
起動時に、プロセス A は誰にも接続しようとしません。プロセス B は
プロセス C は B に対して同じことを行います。および D と C。
次に、selector.select を呼び出して、selectedKeys を反復処理します。key.isValid() && key.isAcceptable() の両方が true の場合、ソケットが私に接続しようとしていると思い、私は呼び出します
key.isValid() && key.isConnectable() の両方が true の場合、サーバーに接続できると思います。電話する
key.isValid() && key.isReadable() が表示されると、受信したメッセージを読み込んでいます。
このプロセスは、A、B、C、D の順にプロセスを開始する限り機能します。B のみを開始すると、finishConnect ステートメントで失敗します。
isConnectable が、このキーのチャネルがソケット接続操作を終了したか、終了に失敗したかをテストするドキュメントを読みました。isConnectable が true で、finishConnect で失敗するのはなぜですか?
java - JavaでのSocketChannelへの書き込みが予期せず繰り返される
私はしばらくの間NIOSocketChannelsを操作しようとしていましたが、SocketChannelへの書き込みに困惑しています。次のコードは私のクライアントからのものです:
}
私の問題は、私がチャンネルに書き出そうとするときに関係しています。コードのこの部分が実行されるたびに、サーバーがデータを処理するのを待たずに、各反復中にデータを書き出すことで、何度もループします。コードを使用してデバッガーを実行すると、サーバーは転送に追いついて処理できるようです(クライアントは要求を再送信し続けますが、少なくともサーバーは転送されたバイトを表示します)。ただし、強制的な遅延なしにコードをそのまま実行すると、クライアントコードは数十回実行され、サーバーは転送を無視しているように見えますが、接続は切断されます。これが私のサーバーコードセクションです-Runnableクラスから実行されることに注意してください:
これはかなりのコードであることは知っていますが、現時点では問題がどこにあるのか特定できません。遅延を強制すると転送が正常に行われるにもかかわらず、クライアントとサーバーが通信できないように見える理由を誰かが推測できますか?
ありがとう。
java - isReadable の仕組みに関する Java NIO の問題/誤解
NIO は、単純化されたケースを除いて、せいぜい不十分に文書化されていることがわかりました。それでも、私はチュートリアルといくつかのリファクタリングを経て、最終的に最も単純なケースに戻りました.0バイトのSocketChannel読み取りでisReadableが起動することがあります. すべての実行で発生しているわけではありません。
以前は別のスレッドでアタッチされたオブジェクトから読み取りを呼び出していましたが、競合状態である可能性があると考えていましたが、セレクターのスレッドで読み取りを行うようになりましたが、それでも問題は解決しません。私はそれが私のテストクライアントである可能性があると思いますが、クライアントソケットはサーバーからの応答を受信するまで閉じてはならないため、何が一貫してトリガーされるのかわかりません。
含まれているコードでは、このスニペットによって送信された「こんにちは」メッセージは、私が期待するように毎回うまくいきます
この後、長さ 0 のソケット チャネルを取得することがあります。そして時々、このスニペットから適切な応答が得られます:
これについての洞察をいただければ幸いです。それは私をゆっくりと殺しています。私はすでにここで答えを見つけようとしましたが、関連していると思われる1つの質問は、私の問題にあまり光を当てませんでした.
前もって感謝します!
以下のコード スニペット:
選択方法:
読み取り方法 (ここでの愚かな部分は無視してください。これは別のスレッドからヤンクされたものです)
クライアント スニペット:
java - Java; NIO-SocketChannelから大量のデータを読み取る
私は、将来他のプロジェクトに使用できる非常に単純なネットワークライブラリを作成しています。現在、読み取り操作の処理に問題があります。SocketChannelsからのイベントの処理を担当するクラスがあり、入力バッファーと出力バッファーも含まれています。バッファを初期化するには、バッファのサイズを定義する必要があります。したがって、デフォルトでは、すべてのバッファのサイズは1024バイトです。
私が抱えている問題は、1024バイトを超えるパケットを読み取ると、例外が発生することです。これは、デフォルトでさらに大きなバッファ(たとえば、1024ではなく2048バイト)を割り当てることで修正できますが、それは簡単な方法のように思えます。特に、その解決策は好きではありません。
私が思いついた解決策は、非常に大きな直接の静的バッファー(Short.MAX_VALUEが大きい)を作成することでした。SocketChannelsからのすべてのデータは、大きなバッファーに読み込まれ、小さなバッファーにコピーされます(データに収まらない場合は、バッファーが拡張されます)。
データを絶えずクリアして大きな「キャリーオーバー」バッファに入れるには、多大なコストがかかるのではないかと心配しています。SocketChannel.available()のようなものがあればいいのですが、最も近い代替手段はSocket.getInputStream()。available()だけですが、そのメソッドはブロックします。そうすれば、バッファが収まるよりも多くの利用可能なデータがある場合、入力バッファ(大きなものではない)を拡張します。残念ながら、私にはできません。そのため、私が考えることができる唯一の解決策は、上記の解決策です。
私はここに尋ねに来ました...あなたの賢明な人の誰かが問題に対しておそらくより良い解決策を持っていますか?また、外部ライブラリは使いたくありません。個人的な好みです。
よろしくお願いします!
謝罪いたします。親友と話をしたところ、そもそも問題ないことに気づきました。かなり長い説明なので説明はしません。謝罪いたします。
ポスターへの注意:質問テキストは絶対に削除しないでください。それは他の人へのガイダンスとして役立ちます。
android - 非ブロック SocketChannel では、関連する Socket はブロックされていますか?
別のスレッドでブロック読み取りを実行しながら、ソケット上の 1 つのスレッドから非ブロック書き込みを実行しようとして、Android アプリを開発しています。私はSocketChannelのドキュメントを調べて、configureBlockingが正確に何をするのかを理解しようとしています。具体的には、ノンブロッキング SocketChannel があり、関連する Socket に socketChannel.socket() でアクセスする場合、その Socket も何らかの方法でノンブロッキングですか? それともブロッキングですか?
言い換えれば、非ブロッキング方向に非ブロッキング SocketChannel を持ち、他の方向に関連する SocketChannel を使用することで、1 つのブロッキング方向と 1 つの非ブロッキング方向の効果を得ることができますか?
java - ReadableByteChannel が read(bytebuffer) でハングする
私はJava 1.6を使用してインスタントメッセンジャーに取り組んでいます。IM は、マルチスレッド (メイン スレッド、受信、および ping) を使用します。TCP/IP 通信には SocketChannel を使用しました。また、サーバーから大きなパッケージを受信する際に問題があるようです。サーバーは1つではなく2つのパッケージを送信し、そこから問題が始まります。最初の 8 バイトごとに、パッケージの種類とサイズが示されます。これが私が読んだ方法です:
そして、テスト中、アカウントにログインしてバディリストをインポートするまでは、すべて問題ありませんでした。ステータスのリクエストをサーバーに送信すると、80 件の連絡先のうち約 10 件が返信されました。だから私はこのようなものを思いついた:
各 readStuff() と readDescription() は、バッファ内の残りのバイトで各パラメータのサイズをチェックしています。
および Receiver.receiver.read() は次のとおりです。
したがって、アプリケーションは起動され、ログに記録され、連絡先が送信されます。サーバーは私のリストの一部だけを私に送り返してきます。しかし、メソッドreadInStatus(ByteBuffer headBuffer)では、リストの残りを強制しようとします。そして今、楽しい部分 - しばらくすると、Receiver.receiver.read()に到達し、バイト = readChannel.read(bb)で停止し、理由がわかりません。しばらくしてもエラーはなく、何もありません。アイデアの。私はこの一週間ずっと戦っていますが、解決策に近づくことはできません。提案をいただければ幸いです。ありがとう。
返信ありがとうございます。はい、ブロッキング SocketChannel を使用しています。ノンブロッキングを試しましたが、暴走して制御不能になったため、アイデアをスキップしました。私が期待するバイトについて-これはちょっと奇妙です。なぜなら、サイズはヘッドで1回だけですが、パッケージ全体ではなく最初の部分のサイズであり、他の部分にはヘッダーバイトがまったく含まれていないからです。それが何バイトになるかは予測できません。その理由は、容量が 255 バイトの記述です。これがまさに私が変数バディを作成した理由です:これpublic synchronized void readInStatus(ByteBuffer headBuffer)
は基本的にバディリストの長さであり、各フィールドを読み取る前に、十分なバイトが残っているかどうかを確認します。そうでない場合はread()を実行します. ただし、説明の前の最後のフィールドは、着信説明の長さを持つ整数です。ただし、何らかの処理が完了するまで、パッケージの長さを判断することは不可能です。@robertその状況でノンブロッキングSocketChannelにもう一度切り替えてみるべきだと思いますか?
java - Java NIO:transferFromからストリームの終わりまで
NIOライブラリで遊んでいます。ポート8888で接続をリッスンしようとしています。接続が受け入れられたら、そのチャネルからにすべてをダンプしますsomefile
。
でそれを行う方法は知っていますがByteBuffers
、非常に効率的だと言われているで動作させたいと思いますFileChannel.transferFrom
。
これは私が得たものです:
だから、私の質問は、「transferFrom
ストリームの終わりに達するまで、いくつかのチャネル」をどのように表現するのですか?
編集:使用されるバッファのサイズは質問とは無関係であるため、1024をBUF_SIZEに変更しました。