我读了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
为超时创建一个计时器。
我的代码有什么问题? 感谢您的参与。