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

时间:2016-01-12 18:31:18

标签: java sockets tcp nio

我读了article和 写了一个处理大约10000个连接的TCP服务器,我还写了一个打开10000个客户端连接来测试服务器程序的程序。当我在同一台PC上使用环回地址与他们通信时,服务器有时无法处理所有连接。所以客户端发送一个帧,但服务器不能发送(程序特定的)确认帧(不是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类将解析帧并返回具有回调函数的worker类。每个ConnectionManager类实例使用ScheduledExecuterService为超时创建一个计时器。

我的代码有什么问题? 感谢您的参与。

0 个答案:

没有答案