如題,在socket編程中報錯java.net.SocketException: Socket closed
1、理解錯誤含義
在數小時無能狂怒后於StackOverflow尋得箴言:
This exception means that you closed the socket, and then continued to try to use it.
你把socket關了,卻還想繼續用,就會報這個錯
2、可能的原因
1. 關閉了IO流(最常見)
也就是說,在你發送、接收操作做完之前別關IO流,也許就能解決;
注意,你可能沒有關閉IO流,或沒有關掉socket的socket.getOutputStream()
和 socket.getInputStream()
;
但它可能被其他IO流關閉影響而自動關閉(見2)
后來才知道 socket 只要在 io流close的情況下 自動關閉,意思就是你想邊發送邊接受最正確的方式就是發送和 接受的操作都做完之后 再一起關閉IO流 完美解決。
內容來自博客:https://blog.csdn.net/qq_33431368/article/details/72331128
2. 我沒有關基礎的IO,為什么還是報了這個錯?
常見於在socket中發送了對象的情況,也即使用了ObjectOutputStream
,
出錯原因:使用完畢的ObjectOutputStream
關閉時,會導致其包裝的OutputStream
也自動關閉。
我的出錯代碼如下
try(OutputStream os = socket.getOutputStream(); InputStream is = socket.getInputStream()) { Resource resource = new Resource(); sendResourceObj(resource,os); os.write("exit".getBytes(StandardCharsets.UTF_8)); } } catch (Exception e) { e.printStackTrace(); }
其中的發送對象的函數如下(本意是為了解耦,把功能盡量模塊化):
public static void sendResourceObj(Resource r,OutputStream os){ try(ObjectOutputStream oos = new ObjectOutputStream(os)) { oos.writeObject(r); oos.flush(); } catch (Exception e) { e.printStackTrace(); } }
可以看到,在sendResourceObj
執行結束后,ObjectOutputStream
就關閉了;
修改方法:
把ObjectOutputStream
和OutputStream
一同,直接放到try-with-resource
的聲明語句中,待使用IO完畢后一起關閉即可
try(OutputStream os = socket.getOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); InputStream is = socket.getInputStream()) { Resource resource = new Resource(); oos.writeObject(resource); oos.flush(); os.write("exit".getBytes(StandardCharsets.UTF_8)); } } catch (Exception e) { e.printStackTrace(); }
初學者記錄一下踩坑經驗,如有錯誤還望路過大佬不吝賜教orz