gpt4 book ai didi

java - 为什么我的非阻塞 Java 服务器拒绝客户端连接?

转载 作者:行者123 更新时间:2023-11-30 09:22:37 25 4
gpt4 key购买 nike

大家好!我正在开发基于 NIO 的服务器,我正在尝试使用简单的客户端程序对其进行测试。

在发布代码之前,我想简要描述一下问题:在服务器立即完成工作的测试用例中,一切正常。但是,当我尝试添加一些现实生活中的行为(例如服务的短暂延迟)时,我收到“java.net.ConnectException:连接被拒绝”异常。更准确地说,100 个客户端线程中的一部分得到了这个连接被拒绝的异常。

我使用以下代码:

客户端

public class TCPClient implements Runnable{

private String name;

public TCPClient(String name)
{
this.name = name;
}

public static void main(String[] args)
{

for(int i=0;i<100;i++)
{
Thread t = new Thread(new TCPClient("thread # "+Integer.toString(i)));
t.start();
}
}

@Override
public void run()
{
Socket socket = null;
OutputStream out = null;
int counter = 0;
try
{
socket = new Socket();
socket.connect(new InetSocketAddress("192.168.3.109",2345), 0);
out = socket.getOutputStream();

byte[] bytes;
while(counter<100)
{
counter++;
bytes = (name+ ", message # "+Integer.toString(counter)+System.lineSeparator()).getBytes();
out.write(bytes);
out.flush();
Thread.sleep(200);
}
}
catch(Exception ex)
{
System.out.println(name+" "+Integer.toString(counter));
ex.printStackTrace(new PrintStream(System.out));
System.out.println();
}
finally
{
if(socket!=null && out!=null)
{
try
{
socket.close();
out.close();
}
catch(Exception ex)
{
System.out.println("client close error");
}
}
}
}

}

服务器

public class TCPServer  {

private Selector selector;
private boolean isRunning;
private ServerSocketChannel server;
private int counter;
private PrintWriter times;
private PrintWriter logger;
private Charset charset;
private CharsetDecoder decoder;
ByteBuffer bb;
long serviceTime,curTime;
Random random;
public TCPServer(int port)
{

counter = 0;
isRunning = false;
serviceTime = 0;
random = new Random();
random.setSeed(System.currentTimeMillis());
bb = ByteBuffer.allocate(2048);

try
{
selector = Selector.open();
server = ServerSocketChannel.open();
server.socket().bind(new InetSocketAddress(port));
server.configureBlocking(false);
server.register(selector, SelectionKey.OP_ACCEPT);


}
catch(Exception ex)
{
System.out.println("initialization error "+ex.getMessage());

}

}


public void startServer() {
isRunning = true;
int acc = 0;
boolean error = false;
while (isRunning) {
try
{


selector.select();

Set keys = selector.selectedKeys();
Iterator it = keys.iterator();
while(it.hasNext())
{
SelectionKey key = (SelectionKey)it.next();

if (key.isConnectable())
{
((SocketChannel)key.channel()).finishConnect();
}

if (key.isAcceptable())
{
//logger.println("socket accepted");
//logger.flush();
acc++;
System.out.println("accepted sockets count = "+acc);
SocketChannel client = server.accept();
client.configureBlocking(false);
client.socket().setTcpNoDelay(true);
client.register(selector, SelectionKey.OP_READ);
}

if (key.isReadable())
{

curTime = System.currentTimeMillis();
SocketChannel sc = (SocketChannel) key.channel();
bb.clear();
int x = sc.read(bb);

if(x==-1)
{
key.cancel();
continue;
}

counter++;

// Thread.sleep(2);
int sum=0;
for(int dummy=0;dummy<4000000;dummy++) // without this delay client works fine
{
sum+=random.nextInt();
sum%=1005;
}

serviceTime+= System.currentTimeMillis() - curTime;
if(counter>=10000)
{
System.out.println("recieved messages count = "+counter);
System.out.println("service time = "+serviceTime+" milliseconds");
}


}
}
keys.clear();
}
catch (Exception ex)
{

System.out.println("error in recieving messages "+ex.getMessage());

}

}
}

public static void main(String[] args)
{

TCPServer deviceServer = new TCPServer(2345);
deviceServer.startServer();

}
}

问题出在 for(dummy...) 循环中——它只是模拟服务延迟——解析传入消息、向数据库写入内容等所需的时间。当延迟很小时代码工作正常,所有 10000 条消息都会到达服务器(100 个客户端线程 X 来自每个客户端的 100 条消息)但是当虚拟循环进行超过 3.000.000 次迭代时,一些客户端线程无法连接到服务器。这里还有一件奇怪的事情是客户端套接字忽略了无限超时属性。我的意思是超时等于零的 socket.connect(InetAddress,timeout) 意味着无限超时——换句话说,服务延迟没有意义,至少我期望这样的行为。

最佳答案

看起来服务器套接字有它允许的最大挂起连接数。 JavaDoc for ServerSocket说:

The maximum queue length for incoming connection indications (a request to connect) is set to 50. If a connection indication arrives when the queue is full, the connection is refused.

现在,我找不到关于 ServerSocketChannel 的相同信息,但我确定它一定存在。

ServerSocketChannel.bind允许配置允许的挂起连接数。

关于java - 为什么我的非阻塞 Java 服务器拒绝客户端连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16432817/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com