public void send(Socket ss,String str)
{
PrintWriter out=null;
try
{
out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(ss.getOutputStream())));
if(str!=null)
{
out.println(str);
out.flush();
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
/*finally
{
try{
if(out!=null)
out.close();
}catch(Exception e){}
}*/
}
当我把上面代码中 finally部分写上时,程序编译没错,运行一会后报错:socket closed!
不写finally{}运行正常.
问题:
1.不写会不会泄露资源?不是应该调用close()方法吗?
2.关闭out会导致把socket也关掉吗?
{
PrintWriter out=null;
try
{
out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(ss.getOutputStream())));
if(str!=null)
{
out.println(str);
out.flush();
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
/*finally
{
try{
if(out!=null)
out.close();
}catch(Exception e){}
}*/
}
当我把上面代码中 finally部分写上时,程序编译没错,运行一会后报错:socket closed!
不写finally{}运行正常.
问题:
1.不写会不会泄露资源?不是应该调用close()方法吗?
2.关闭out会导致把socket也关掉吗?
1)要调用out.close()操作,这是个好习惯。否则可能会“泄漏资源”。
2)只有当你认为通信全部结束,不需要数据交换时,再去:先关闭流,然后关闭socket.
上面的send()函数将被其他函数调用,ss在被send()用过后我想在后面继续使用ss;
不close()泄露资源,调用了又会关闭ss,我将何去何从?out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(ss.getOutputStream())));
out到底与ss是什么关系?
只有本client会获得所有的client的IP,即服务器不向其他人发送。
以下为服务程序。(不会是我的程序结构设计错了吧,导致我“不close()泄露资源,调用了又会关闭ss”)
import java.net.*;
import java.io.*;
import java.util.LinkedList;public class Server
{
ServerSocket ss;
Socket s; static LinkedList arrList=new LinkedList(); //用来存储所有连接到服务器的socket(客户) public Server() throws Exception{
ss=new ServerSocket(2345);
}
public static LinkedList getList()
{
refresh();
return arrList;
}
public void init() throws Exception{
while(true){
s=ss.accept();
System.out.println("Server listening...");
arrList.add(s); //有刚连接的socket,将之加到arrList
new MyThread((Socket)s).start(); //为每一个连接到服务器的客户创建一个线程
}
}
public static void refresh() //更新arrList(去掉断开的连接)
{
for(int i=arrList.size();i>0;i--)
{
if(((Socket)arrList.get(i-1)).isClosed())
arrList.remove(i-1);
}
}
public static void main(String[] args) throws Exception
{
Server s=new Server();
s.init();
}
}class MyThread extends Thread{
Socket s;
public MyThread(Socket s) //将刚创建的Socket传到专门处理它的thread
{
this.s=s;
}
public void run()
{
BufferedReader br=null;
try{ br =new BufferedReader(new InputStreamReader(s.getInputStream()));
while(true)
{
String temp=br.readLine();
if(temp.startsWith("/list"))
ListTheList();
else
broadcast("message from "+s.getInetAddress()+":\t"+temp);
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
try
{
if(br!=null)
br.close();
}catch(Exception e){}
} }
public void broadcast(String str)
{
LinkedList LL=Server.getList();
for(int i=0;i<LL.size();i++)
{
send(((Socket)LL.get(i)),str);
}
}
public void ListTheList() //列出所有的client
{
LinkedList LL=Server.getList();
StringBuffer sb=new StringBuffer();
if(LL.size()!=0){
for(int i=0;i<LL.size();i++)
{
sb.append(((Socket)LL.get(i)).getInetAddress()+"is in the list\n");
}
send(s,sb.toString());
}
}
public void send(Socket ss,String str)//向连接ss发送 str
{
PrintWriter out=null;
try
{
out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(ss.getOutputStream())));
if(str!=null)
{
out.println(str);
out.flush();
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
/*finally
{
try{
if(out!=null)
out.close();
}catch(Exception e){}
}*/
}
}
你的程序的目的,我已清楚.根据这个目的,我认为,你的程序结构在设计时有比较大的不妥,所以才有你的这个问题.
我想,结构能否如下设计:
1)每一个客户,对应服务器方的一个线程.也只有这个线程才知道如何与它的客户进行通信.或都说,与这个客户进行通信的信息都委托给这个线程来进行.基于这一个考虑,LinkedList arrList存放的不是Socket对象,而是线程.
2)每一个线程全权自己管理自己的与它的客户的网络通信,故,当线程创建并启动后,由线程进行网络流的I/O.当通信结束时,由线程进行流的关闭,并关闭它的Socket对象.
3)每一个线程向外界开放一个方法:send(String msg),用于自己及其它人通过该方法,向本线程的客户发送(或转发)信息.
4)arrList是一个临界区,至少开放两个方法:一个用于线程将自己加入到arrList中.另一个用于当线程通过结束要关闭之前,将自己从arrLIst中删除.而broadcast(String str) 功能则用于依次遍历arrList,对其中的每一个线程调用它的send(str)即可.