我修改了可用的示例代码here for Client and Server我的客户:
public class Client {
public static void main(String[] args) {
int n=10000;
SocketTest [] st= new SocketTest[n];
for(int i=0;i<n;i++)
st[i]= new SocketTest("hi");
for(int i=0;i<n;i++)
new Thread(st[i]).start();
}
}
class SocketTest implements Runnable {
private String message = "";
private Selector selector;
private int i;
public SocketTest(String message){
this.message = message;
}
@Override
public void run() {
SocketChannel channel;
try {
selector = Selector.open();
channel = SocketChannel.open();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_CONNECT);
channel.connect(new InetSocketAddress("127.0.0.1", 8511));
while (!Thread.currentThread().isInterrupted()){
selector.select();
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()){
SelectionKey key = keys.next();
keys.remove();
if (!key.isValid()) continue;
if (key.isConnectable()){
connect(key);
System.out.println("I am connected to the server");
}
if (key.isWritable()){
write(key);
}
if (key.isReadable()){
read(key);
}
}
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
close();
}
}
private void close(){
try {
selector.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void read (SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer readBuffer = ByteBuffer.allocate(1000);
readBuffer.clear();
int length;
try{
length = channel.read(readBuffer);
} catch (IOException e){
System.out.println("Reading problem, closing connection");
key.cancel();
channel.close();
return;
}
if (length == -1){
System.out.println("Nothing was read from server");
channel.close();
key.cancel();
return;
}
readBuffer.flip();
byte[] buff = new byte[1024];
readBuffer.get(buff, 0, length);
//length=buff.length;
String fromserver = new String(buff,0,length,"UTF-8");
length = fromserver.length();
System.out.println("Server said: "+fromserver);
key.interestOps(SelectionKey.OP_WRITE);
}
private void write(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
i++;
message = "location now "+i;
try{
Thread.sleep(5000);
}
catch(InterruptedException ie)
{
System.out.println(""+ie);
}
channel.write(ByteBuffer.wrap(message.getBytes()));
// lets get ready to read.
key.interestOps(SelectionKey.OP_READ);
}
private void connect(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
try
{
if(!channel.finishConnect())
System.out.println("* Here *");
}
catch(ConnectException e)
{
System.out.println("BP 1");
e.printStackTrace();
//channel.close();
//key.cancel();
//return;
}
/*if (channel.isConnectionPending()){
while(!channel.ffinishConnect()){
System.out.println("not connected");
}
}*/
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_WRITE);
}
}
我通过创建多个线程在同一台计算机上创建多个客户端。线程数由n的值确定。当我运行很少的客户端时,我没有遇到任何问题,但是当我使用500的n(即500个客户端线程)运行时,某些线程可以正确运行,但是在某些情况下我会遇到以下问题:java.net.ConnectException: Connection refused: no further information
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(Unknown Source)
at SocketTest.connect(Client.java:143)
at SocketTest.run(Client.java:61)
第143行是:if(!channel.finishConnect())
因此,当我阅读此方法的文档时,它会抛出:
NoConnectionPendingException-如果未连接此通道并且尚未启动连接操作。
ClosedChannelException-如果此通道已关闭。
AsynchronousCloseException-如果在进行连接操作时另一个线程关闭了此通道。
ClosedByInterruptException-如果在进行连接操作时另一个线程中断了当前线程,从而关闭了通道并设置了当前线程的中断状态。
IOException
-如果发生其他一些I / O错误。但是例外是ConnectException。我尝试捕获它,但是它没有进入捕获块。
任何帮助将不胜感激。谢谢。编辑:
我正在窗户上工作。我尝试更改n的值,以查看创建了多少个客户端以及导致了多少个异常,这些都是结果(我知道在每个测试之后等待更多的时间将允许更多的开放套接字,就像在TIME_WAIT之后释放每个测试场景之后):n clients connected(by keeping a count at server)
1000 522
2000 568
3000 626
4000 600 (maybe I gave less time before successive runs)
5000 1345
6000 1389
我对只有这么多的客户端才能建立连接感到困扰。任何人都可以建议更好的参考来阅读Client Server NIO。
编辑2
正如EJP在其评论中提到的,“ Backlog Queue”窗口已满。我修改了客户端代码以生成100个线程,然后休眠5秒钟,这样队列上的负载就不大了,并且大多数连接都成功了(但是,当建立10,000个连接时,仍然有些失败了。)
我修改了此处可用于客户端和服务器的示例代码。我的客户端:公共类Client {public static void main(String [] args){int n = 10000; SocketTest [] st =新的SocketTest [n]; ...
ConnectException: connection refused
表示没有任何内容在您尝试连接的IP:端口上侦听,或在服务器的侦听积压队列已满的某些平台上侦听。如果将其抛出并正确捕获,则肯定会捕获。您需要扩展实际发生的情况以及实际捕获代码的外观,以获取进一步的帮助。
我相信您拥有500个线程的ConnectException
不是来自SocketTest.connect()
。它可能来自其他任何IO方法。
尝试使用命令进行Telnet-