![](/img/trans.png)
[英]In Java NIO, is a selector useful for a client SocketChannel?
[英]Maximum size of data that can be fetched from a client socket using socketChannel of nio package in java
使用SocketChannel sc =(SocketChannel)key.channel();
,我們可以將數據從端口提取到緩沖區。
為了在不丟失數據的情況下從端口連續接收數據,代碼應該如何?
這是我的代碼
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
public class MultiPortEcho
{
private int ports[];
private ByteBuffer echoBuffer = ByteBuffer.allocate(32000);
public MultiPortEcho( int ports[] ) throws IOException
{
this.ports = ports;
go();
}
private void go() throws IOException
{
// Create a new selector
Selector selector = Selector.open();
// Open a listener on each port, and register each one
// with the selector
for (int i=0; i<ports.length; ++i)
{
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking( false );
ServerSocket ss = ssc.socket();
InetSocketAddress address = new InetSocketAddress( ports[i] );
ss.bind( address );
SelectionKey key = ssc.register( selector, SelectionKey.OP_ACCEPT );
System.out.println( "Going to listen on "+ports[i] );
}
while (true)
{
int num = selector.select();
System.out.println("num::::"+num);
Set selectedKeys = selector.selectedKeys();
Iterator it = selectedKeys.iterator();
while (it.hasNext())
{
SelectionKey key = (SelectionKey)it.next();
if ((key.readyOps() & SelectionKey.OP_ACCEPT)== SelectionKey.OP_ACCEPT)
{
// Accept the new connection
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking( false );
// Add the new connection to the selector
SelectionKey newKey = sc.register(selector,SelectionKey.OP_READ);
it.remove();
System.out.println( "Got connection from "+sc );
}
else if ((key.readyOps() & SelectionKey.OP_READ)== SelectionKey.OP_READ)
{
// Read the data
SocketChannel sc =(SocketChannel)key.channel();
System.out.println("sc::::"+sc);
// data to fetched from channel and dump into the datatbase
int bytesEchoed = 0;
//while(true)
{
echoBuffer.clear();
int r = sc.read(echoBuffer);
System.out.println("r:::" + r);
/*int pos=echoBuffer.position();
System.out.println("pos:::" +pos);*/
if (r == -1)
{
//echoBuffer.flip();
echoBuffer.rewind();
byte[] array = new byte[100000];
while (echoBuffer.hasRemaining())
{
int n = echoBuffer.remaining();
System.out.println("size:" + n);
echoBuffer.get(array,0,n );
System.out.println(new String(array,0,n));
key.cancel();
it.remove();
}
}
/*int pos=echoBuffer.position();
System.out.println("pos:::" + pos);
if(r<=0)
{
echoBuffer.flip();
for (int j = 0; j < pos; j++ )
{
String ss =Integer.toHexString(echoBuffer.get());
if (ss.length() == 1)
System.out.print("0" + ss + " ");
else if (ss.length() > 2)
System.out.print(ss.substring(6) + " ");
else System.out.print(ss + " ");
}
break;
}
echoBuffer.flip();
sc.write( echoBuffer );
bytesEchoed += r;*/
}
//System.out.println( "Echoed "+bytesEchoed+" from "+sc );
//it.remove();
}
}
//System.out.println( "going to clear" );
// selectedKeys.clear();
//System.out.println( "cleared" );
}
}
static public void main( String args[] ) throws Exception
{
FileOutputStream fileoutputstream = new FileOutputStream("MultiPort.txt", false);
PrintStream printstream = new PrintStream(fileoutputstream);
System.setOut(printstream);
if (args.length<=0) {
System.err.println( "Usage: java MultiPortEcho port [port port ...]" );
System.exit( 1 );
}
int ports[] = new int[args.length];
for (int i=0; i<args.length; ++i) {
ports[i] = Integer.parseInt( args[i] );
}
new MultiPortEcho( ports );
}
}
您可以閱讀的最大大小實際上受到您擁有的內存量的限制。
但是,您無需讀取超大塊以提高效率。 你會發現1 MB就足夠了。 實際上,您可能會發現4KB的塊足夠大,可以為1 Gb連接獲得最大帶寬。
對總體設計的評論:
編寫網絡服務器有兩種基本方法。 阻止和非阻塞。 2008年,我們的任務是在Python中實現高性能網絡服務器。 在使用非阻塞嘗試了幾種不同的方法后,我們發現使用它更容易 ,更清晰:
這樣每個線程都可以坐下來等待數據直到它死亡的那一天,當它收到一個完整的數據包時,它就會采取行動。
僅供考慮。
您可以在此SocketChannelHandler中找到一些潛在客戶,其中readFromChannel()
函數可能對您有用。
public void readFromChannel() {
try {
[...]
if (readBuffer != null) {
readBuffer.flip();
receivingBroker.broker(readBuffer, false);
if (readBuffer != null) {
readBuffer.clear();
readBuffer = null;
}
}
if (readBuffer == null || !readBuffer.hasRemaining()) {
getThread().removeInterestOp(this, SelectionKey.OP_READ);
getThread().addInterestOp(this, SelectionKey.OP_WRITE);
}
if (receivingBroker.isClosed()) {
if (getChannelListener() != null) {
getChannelListener().readFinished(this);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
作為第一個修復,您應該使用key.cancel()刪除該行。 保持它將取消密鑰並確保在第一次讀取后不考慮密鑰 - 這將有效地阻止您在之后閱讀任何內容。
當您使用NIO接受連接時,您可以獲取套接字並設置相應的輸入/輸出緩沖區大小。
socketChannel.socket().setReceiveBufferSize(512);
socketChannel.socket().setSendBufferSize(16);
由於NIO大量使用操作系統的網絡堆棧,這只是一個提示。 所有這些實際上都在Socket JavaDoc中有很好的記錄
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.