
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
昆明达内培训的小编这一期给大家讲Java SE中TCP协议网络编程。
之前的代码中关闭了socket对象的输入流与输出流,但并没有关闭掉socket对象,会造成服务器资源的浪费,应通过调用socket的close()方法来关闭当前的socket对象。
因此,可以通过创建一个 ServerScanThread线程,使其一直在后台运行,扫描看哪些socket对象的Input Stream与OutputStream均已关闭,当扫描到当前socket对象的输入输出流均已关闭,则关闭当前socket对象。
扫描线程代码:
public class ServerScanThread extends Thread {
public static List<Socket> socketList = new LinkedList<Socket>(); //实例化一个静态列表,使其存放Socket,使用LinkedList便于删除
public ServerScanThread(){
setDaemon(true);//设置为后台线程
start();
}
public void run(){
while(true){
//1.我要去扫描整个集合,如果当前集合是空的,我就去睡觉去喽
while(socketList == null ||socketList.size()<= 0){
System.out.println("这会儿集合里没有socket,我先睡觉10s");//测试代码
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//2.如果运行到这里,则说明socketList中有元素,则有开始扫描判断其socket对象是否已经关闭了其输入流和输入流。
for(int i = 0;i<socketList.size();i++){
Socket socket = socketList.get(i);//从socketList集合中获得一个socket对象。
if(socket.isInputShutdown() & socket.isOutputShutdown()){
try {
socket.close();//关闭当前socket对象
socketList.remove(i);//从当前列表中移除当前socket对象。
System.out.println("有一个socket被关闭了");//测试代码
//i--; LinkedList在移除掉一个元素后,其后边的元素下标统统会减一,为保证不会跳过某一个元素,可在此处将i自减,也可以不因为会进行再次扫描
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
try {
Thread.sleep(5000);//扫描完一遍之后休息五秒钟
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//整个线程完成后可以在Server中进行调用。
}
}
服务器端代码:
public class Server1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
@SuppressWarnings("resource")
ServerSocket server = new ServerSocket(9880);
new ServerScanThread();
while (true){
Socket client = server.accept();
ServerScanThread.socketList.add(client);//在socketList集合中加入socket实例对象
System.out.println("来自"+ client.getInetAddress().getHostAddress()+"的客户端已连接成功!");
if(client != null){
//开始对话
new WriterThread("服务端",client);
new ReaderThread("服务端",client);
}
}
} catch (IOException e) {
e.printStackTrace();
}
input.close();
}
}
当没有客户端运行时的输出:
此时没有socket对象,程序不停在内部的第一个while循环里运行,每隔十秒打印一次。
当运行客户端但不关闭socket的输入输出流时的输出:
由于是先运行的服务器端,所以while循环先会执行一次,这次循环中还没有socket对象,当客户端开始运行时,由于没有输入byebye,所以不会关闭socket的输入流与输出流,程序会执行到内部for循环不断循环。
当运行客户端并且关闭socket的输入输出流时的输出:
在两端分别输入byebye关闭输入输出流之后,当前socket被扫描出来并关闭。因为设置的该扫描线程为一个后台线程,当Server停止运行时,该线程也停止。
了解详情请登陆广州达内Android培训官网(gz.android.tedu.cn)!