[英]java socket server program not accepting connections after some time
我有一个套接字客户端应用程序,该应用程序侦听指定端口上主线程中的传入连接,接受传入连接并为每个连接启动一个用户线程。
此设置有一天会起作用,然后应用程序将停止接受任何新的新连接。 恢复的唯一方法是重新启动应用程序。 我不知道为什么会这样...这是我的主要角色,它为每个连接启动并启动一个新线程。
while(ServerOn)
{
ServerSocket myServerSocket;
private static ArrayList<Socket> connecitons;
try {
// Accept incoming connections.
Socket conn = myServerSocket.accept();
// adds the new connections to the socket
connections.add(conn);
// accept() will block until a client connects to the server.
// If execution reaches this point, then it means that a client
// socket has been accepted.
// For each client, we will start a service thread to
// service the client requests.
// Start a Service thread
ServerThread cliThread = new ServerThread(conn);
cliThread.start();
} catch (IOException ioe) {
System.out.println("Exception encountered on accept. Ignoring. Stack Trace :");
ioe.printStackTrace();
}
}
try {
myServerSocket.close();
System.out.println("Server Stopped");
} catch (Exception ioe) {
System.out.println("Problem stopping server socket");
System.exit(-1);
}
}
请帮忙。
编辑1
这是类声明:
class ServerThread extends Thread {
Socket conn;
boolean m_bRunThread = true;
InputStream in = null;
OutputStream outStream = null;
//calling the 1-argument constructor with the socket parameters
ServerThread(Socket s) {
conn = s;
}
//Subclasses of Thread should override this method.
public void run() {
//lot of variables declared here.
try {
// Class InputStream is used for receiving data (as bytes) from client.
in = conn.getInputStream();
// Class OutputStream is used for sending data (as bytes) to client.
outStream = conn.getOutputStream();
/*
* 1. Go to Read Thread
* 2. Check for incoming data stream from Client
* 3. Go to read routine and process only if the data is received from the client
* 4. If there is no data for X minutes then close the socket.
*/
conn.setSoTimeout(time in milliseconds);
String inLine=null;
while (m_bRunThread) {
// read incoming stream
while ((c=in.read(rec_data_in_byte))!= -1)
{...............
然后运行方法继续...
我的观察是基于您提供的上述代码。 我在下面看到的东西对我来说毫无疑问:
private static ArrayList<Socket> connecitons;
我不需要此列表。 根据代码,我们总是为每个请求在此列表中添加conn
对象。 我们不会在任何地方删除它们(我没有看到完整的代码)。 如果是这种情况,那么此列表的大小总是在增加。 并且可能导致OutOfMemoryError。
while (m_bRunThread) {....}
在ServerThread类的run()方法中,变量m_bRunThread
始终为true。 如果是这种情况,那么该线程将永远不会终止。 所以没有 活动线程的数量不断增加。 它将使应用程序无响应。 对于ConcurrentModificationException
:由于您没有使用Iterator
(或for-each循环)在列表上进行迭代,因此即使在多线程情况下也永远不会抛出此异常。
m_bRunThread
上的外部循环应被删除。 您只需要内部读取循环,当它终止或遇到异常时,它应该关闭套接字。
我观察到的另一件事。 按照提供的代码,对于每个传入连接,您都在创建一个新的服务线程。 但是我不认为每次创建一个新线程都是一个好主意。
因为假设如果每秒有1000个连接,则意味着我们每秒创建1000个新线程,因此,这意味着管理1000个线程会产生很大的开销。
由于线程的上下文切换的开销,应用程序可能变得无响应。 其次,将有频繁的GC(垃圾收集器)循环,有时又可能导致STW(停止世界)这种情况。
所以我的建议是:
您可以使用某种线程池,可能是Executor框架,我们可以通过提供参数(例如核心池大小,最大池大小,保持空闲线程的存活时间等)来创建自己的ThreadPoolExecutor
。 因此,现在您不必管理线程的创建和生命周期。 现在可以重新使用空闲线程。 您的应用程序将具有更高的响应速度,因为频繁使用GC的机会会更少。
即使您可以使用Executor的框架内置固定大小的线程池实现,也不需要管理其余开销,除非您必须传递总编号。 参数中要存在的线程数,以供您处理请求。
下面是示例代码:
private Executor executor = Executors.newFixedThreadPool(10);
private ArrayList<Socket> connecitons = new ArrayList<>();
while(ServerOn)
{
ServerSocket myServerSocket;
try {
// Accept incoming connections.
Socket conn = myServerSocket.accept();
connections.add(conn);
executor.execute(new ServerThreadRunnable(conn));
} catch (IOException ioe) {
System.out.println("Exception encountered on accept. Ignoring. Stack Trace :");
ioe.printStackTrace();
}
}
try {
myServerSocket.close();
System.out.println("Server Stopped");
} catch (Exception ioe) {
System.out.println("Problem stopping server socket");
System.exit(-1);
}
下面是任务的实现。
class ServerThreadRunnable implements Runnable {
private Socket conn;
ServerThread(Socket s) {
conn = s;
}
public void run() {
//Here the implementation goes as per your requirement
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.