我在这里读到了一些关于这个问题的答案,但我对它们并不满意,所以我决定自问。所以我知道有类似的问题,但由于答案对我不起作用,我问自己。
我有一个应用程序允许2个用户相互连接(一个用作服务器,另一个用作客户端)。他们将通过该套接字连接发送文件。我正在使用一个内部有2个线程的服务,一个用于读取,另一个用于发送用户选择的文件。
问题在于:如果客户端通过在Android菜单(正在运行的应用程序)上刷它来关闭应用程序,然后服务器(另一个人)试图向他发送一些东西,在我的认为它应该抛出IOException,因为套接字流的另一端已经结束了。但它没有这样做,我不知道为什么。如果我尝试向离开的人发送内容,我想展示一个Toast。
编辑:刚注意到它总是停在指令out.reset();
你们有没有人知道为什么不抛出这个异常? 什么是可能的解决方案。
PS:这是一个精简版应用,所以发送Keep Alive消息不是一个好的解决方案。此外,它已经展示了我有一两次的吐司,但后来我无法再次复制这种行为。
这是我的代码,我不想发生这种情况:
ClientHandler tmp = connectedClients.get(key);
ObjectOutputStream out = tmp.getOut();
Socket s = tmp.getSocket();
if(s.isClosed()){
System.out.println("The socket of this client "+key + " is closed!");
}
if(s.isOutputShutdown()){
System.out.println("The output of this client is shutdown !");//only checks this side, the other one is the one that is shutdown
}
System.out.println("changed the culpado to : "+1);
createSendNotification();
File apkToSend;
for(int i=0;i<listOfApps.size();i++){
System.out.println("Item do be sent is : "+i);
HighwayGridViewAppItem tmpItem=listOfApps.get(i);
filePath=tmpItem.getFilePath();
appName=tmpItem.getAppName();
System.out.println("his filepath to send is : "+filePath);
System.out.println("his appname to send is : "+appName);
couldSend=false;
apkToSend=new File(filePath);
if(apkToSend.exists()){//do i reallly need this if?
apkToSendSize=apkToSend.length();
System.out.println("File size: " +apkToSendSize);
try{
out.writeObject(appName +": "+ apkToSendSize);//appName to send to have the name of the file
byte[] buffer = new byte [8192];
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(apkToSend));
int count;
totalToSend =0;
showSendProgress();
while((count=bis.read(buffer))!=-1){
out.write(buffer,0,count);
totalToSend +=count;
out.reset();
System.out.println("ServerComm send thread - already sent this ammount : "+ totalToSend);
}
out.flush();
bis.close();
}
catch ( IOException e){
System.out.println("It is throwing the input output exception");
e.printStackTrace();
connectedClients.remove(key);
if(clients.size()<=1){
h.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context, "No one is in your group.", Toast.LENGTH_SHORT).show();
}
});
i=listOfApps.size()+1;
}else{
System.out.println("Has more than one");
}
}
PS:当我尝试发送到“关闭”的客户端时,它会输出一些“ServerComm发送线程 - 已经发送了这个ammount:”+ totalToSend“然后才停止,这是我认为应该抛出异常,但它只是停止,并没有给出任何错误,应用程序继续其生命,但我需要向用户提供一些问题,一些问题发生了变化。
此外,我在此服务的onCreate方法中创建了Handler,它正在使用主循环器正确创建(因为它在服务中,它需要不同的创建)。
提前谢谢你们。
编辑:最后,在将近4分钟后,它会抛出一个SocketException,但我不能等那么久。
答案 0 :(得分:0)
仅仅因为Android处理应用程序并不意味着内部所有打开的连接都已关闭,很可能您需要检测Android事件然后执行明确关闭打开套接字的代码而不是等待Android最终照顾它。否则,您将不得不等待通过调用终结器的垃圾收集来关闭套接字。
这篇文章详细介绍了Android事件和onDestroy方法:How to close Android application?
答案 1 :(得分:0)
如果您需要立即断开连接检测,那么您将不得不实施自己的ping / keep alive机制,这通常意味着发送数据包并持续确认它们以便能够更可靠地捕获异常。