Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java NIO TCP服务器连接处理问题_Java_Sockets_Tcp_Nio - Fatal编程技术网

Java NIO TCP服务器连接处理问题

Java NIO TCP服务器连接处理问题,java,sockets,tcp,nio,Java,Sockets,Tcp,Nio,我读了一本书 编写了一个TCP服务器,它可以处理大约10000个连接,我还编写了一个程序,可以打开10000个客户端连接来测试服务器程序。当我在同一台电脑上使用环回地址与他们通信时,服务器有时无法处理所有连接。因此,客户端发送一个帧,但服务器无法发送(特定于程序的)确认帧(不是tcp ack)。但如果我用大约1000个连接运行这个模拟,一切都会正常工作 以下是我的连接处理程序代码: public void run() { while (true) { try {

我读了一本书 编写了一个
TCP
服务器,它可以处理大约10000个连接,我还编写了一个程序,可以打开10000个客户端连接来测试服务器程序。当我在同一台电脑上使用环回地址与他们通信时,服务器有时无法处理所有连接。因此,客户端发送一个帧,但服务器无法发送(特定于程序的)确认帧(不是tcp ack)。但如果我用大约1000个连接运行这个模拟,一切都会正常工作

以下是我的连接处理程序代码:

    public void run() {
    while (true) {
        try {
            synchronized (this.pendingChanges) {
                Iterator changes = this.pendingChanges.iterator();
                while (changes.hasNext()) {
                    ChangeRequest changeRequest = (ChangeRequest) changes.next();
                    if (changeRequest.socket.isOpen() == true) {
                        SelectionKey key = changeRequest.socket.keyFor(this.selector);
                        key.interestOps(changeRequest.ops);
                    }
                }
                this.pendingChanges.clear();
            }
            this.selector.select();
            Iterator selectedKeys = this.selector.selectedKeys().iterator();
            while (selectedKeys.hasNext()) {
                SelectionKey key = (SelectionKey) selectedKeys.next();
                selectedKeys.remove();
                if (!key.isValid()) {
                    continue;
                }
                if (key.isAcceptable()) {
                    this.accept(key);
                } else if (key.isValid() && key.isReadable()) {
                    this.read(key);
                } else if (key.isValid() && key.isWritable()) {
                    this.write(key);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }catch(CancelledKeyException ce){
            //System.out.println("Key zaten cancel edilmis");
        }
    }
}
private void read(SelectionKey key) throws IOException {
    SocketChannel socketChannel = (SocketChannel) key.channel();
    if (socketChannel.isOpen() == true) {
        this.readBuffer.clear();
        int numRead;
        try {
            numRead = socketChannel.read(this.readBuffer);
        } catch (IOException e) {
            if (socketChannel.isOpen()) {
                socketChannel.close();
                queueObject.socket = socketChannel;
                queueObject.isAlive = false;
                this.worker.addSocketToQueue(queueObject);
            }
            if (socketChannel.isRegistered()) {
                key.cancel();
            }
            //this.worker.deleteConnection(socketChannel);
            return;
        }
        if (numRead == -1) {
            if (socketChannel.isOpen()) {
                socketChannel.close();
                queueObject.socket = socketChannel;
                queueObject.isAlive = false;
                this.worker.addSocketToQueue(queueObject);
            }
            if (socketChannel.isRegistered()) {
                key.cancel();
            }
            // System.out.println("Socket kapatildi");
            // this.worker.deleteConnection(socketChannel);
            return;
        }
        queueObject.data = readBuffer.array();
        queueObject.size = numRead;
        queueObject.socket = socketChannel;
        queueObject.isAlive = true;
        this.worker.addSocketToQueue(queueObject);
    }
}
这是我的工作线程代码:

public class Worker implements Runnable, ConnectionManager.ConnectionCallbacks {

private LinkedList<QueueObject> queue = new LinkedList<>();
private HashMap<SocketChannel, ConnectionManager> connections = new HashMap<>();
private DatabaseWorker databaseWorker;
private int connectionCount = 0;
NioServer server;
Thread t;
int counter = 0;
private int actPackCount = 0;

public Worker(NioServer server) {
    this.server = server;
    t = new Thread(this);
    t.setPriority(Thread.NORM_PRIORITY+1);
    t.start();
    databaseWorker = new DatabaseWorker();
}

public void addSocketToQueue(QueueObject queueObject) {

    byte[] datacopy = new byte[queueObject.size];
    System.arraycopy(queueObject.data, 0, datacopy, 0, queueObject.size);
    synchronized (queue) {
        queue.add(new QueueObject(queueObject.socket, datacopy, queueObject.size, queueObject.isAlive));
        queue.notify();
    }
}

public void createConnection(SocketChannel socket) {

   // synchronized (this.connections) {
        connectionCount++;
        ConnectionManager connectionManager = new ConnectionManager(this, socket, databaseWorker);
        this.connections.put(socket, connectionManager);
        try(BufferedWriter bw=new BufferedWriter(new FileWriter("/home/yusuf/NetBeansProjects/YososServer/ConnectionCreateLog",true))){
            bw.write("Connection Create:"+connectionCount);
            bw.newLine();
        }catch(IOException e){

        }
   // }
}

public void deleteConnection(SocketChannel socket) {
    synchronized (this.connections) {
        this.connections.remove(socket);
    }
}

@Override
public void run() {
    QueueObject queueObject;
    ConnectionManager connectionManager;
    while (true) {
        synchronized (queue) {
            while (queue.isEmpty()) {
                try {
                    queue.wait();
                } catch (InterruptedException e) {

                }
            }
            queueObject = queue.remove();
        }
        synchronized (this.connections) {

            connectionManager = this.connections.get(queueObject.socket);
        }
        if (connectionManager != null) {
            connectionManager.addData(queueObject);
            if (queueObject.isAlive = false) {
                deleteConnection(queueObject.socket);
            }
        }
    }
}
公共类工作程序实现可运行的ConnectionManager.ConnectionCallbacks{
私有LinkedList队列=新建LinkedList();
私有HashMap连接=新建HashMap();
私有数据库工作者数据库工作者;
私有int connectionCount=0;
NioServer服务器;
螺纹t;
int计数器=0;
私有int actPackCount=0;
公共工作者(NioServer服务器){
this.server=server;
t=新螺纹(本螺纹);
t、 setPriority(线程规范优先级+1);
t、 start();
databaseWorker=新的databaseWorker();
}
public void addSocketToQueue(QueueObject QueueObject){
byte[]datacopy=新字节[queueObject.size];
System.arraycopy(queueObject.data,0,datacopy,0,queueObject.size);
已同步(队列){
添加(新的QueueObject(QueueObject.socket、datacopy、QueueObject.size、QueueObject.isAlive));
queue.notify();
}
}
public void createConnection(SocketChannel套接字){
//已同步(此。连接){
connectionCount++;
ConnectionManager ConnectionManager=新的ConnectionManager(this、socket、databaseWorker);
this.connections.put(套接字、connectionManager);
try(BufferedWriter bw=new BufferedWriter(new FileWriter(“/home/yusuf/NetBeansProjects/YososServer/ConnectionCreateLog”,true))){
写入(“连接创建:+connectionCount”);
换行符();
}捕获(IOE异常){
}
// }
}
公共连接(插座通道插座){
已同步(此。连接){
此。连接。移除(插座);
}
}
@凌驾
公开募捐{
队列对象队列对象;
连接管理器连接管理器;
while(true){
已同步(队列){
while(queue.isEmpty()){
试一试{
queue.wait();
}捕捉(中断异常e){
}
}
queueObject=queue.remove();
}
已同步(此。连接){
connectionManager=this.connections.get(queueObject.socket);
}
if(connectionManager!=null){
connectionManager.addData(queueObject);
if(queueObject.isAlive=false){
deleteConnection(queueObject.socket);
}
}
}
}
ConnectionManager
类将解析帧并返回到带有回调函数的worker类。每个
ConnectionManager
类实例使用
ScheduledExecuterService
创建一个计时器,用于超时

我的代码中有什么问题?
谢谢你的关注。

你分析过你的代码吗?是的,我在非阻塞模式下使用它。“我在非阻塞模式下使用它”不是“你分析过你的代码”的答案。你不需要所有这些排队。这是一个城市神话,最终源于亚马逊南非某个人的一篇质量差的文章。你只需要
Selector.wa基普()
如果您正在注册或取消来自另一个线程的频道,那么您为什么要这样做首先是个谜。不要编写自己的nio服务器,请使用一个框架,例如。当存在实际队列时,也不要滥用
LinkedList
作为队列。@EJP您是正确的,我的代码来自地址。但是,我如何在不排队的情况下解析和处理所有帧呢?你分析过你的代码吗?是的,我在非阻塞模式下使用它。“我在非阻塞模式下使用它”并不是“你分析过你的代码了吗?”的答案。你不需要所有这些排队。这是一个城市神话,最终源于亚马逊南非某个人的一篇低质量文章只需要
Selector.wakeup()
如果您正在注册或取消来自另一个线程的频道,那么您为什么要这样做首先是个谜。不要编写自己的nio服务器,请使用一个框架,例如。当存在实际队列时,也不要滥用
LinkedList
作为队列。@EJP您是正确的,我的代码来自地址。但是,如何在没有队列的情况下解析和处理所有帧呢