Socket學習文檔 http://developer.51cto.com/developer/javabook/images/3.pdf
1.socket.shutdownOutput();
文檔解釋:
Disables the output stream for this socket. For a TCP socket, any previously written data will be sent followed by TCP's normal connection termination sequence. If you write to a socket output stream after invoking shutdownOutput() on the socket, the stream will throw an IOException.
if an I/O error occurs when shutting down this
具體可以參考這個帖子 http://www.blogjava.net/xuechen0721/archive/2006/04/29/44040.html
大致就是說,.shutdownOutput()這個方法是關閉輸出流,而不是關閉Socket對象本身,把這個方法放到一個流的末尾,表示我已經給你(客戶端或服務端)傳完信息了,你不需要在等待接收信息了。
.shutdownInput()這個方法類似。
不用socket.shutdownOutput()來做每段消息的結束標志時,還可以用下邊的方法
//pw.write("這是"+info+"包裝后的返回結果\r\n"); //注意\r\n是作為結束標志的 pw.println("這是"+info+"包裝后的返回結果"); //prinltn和prinlt,write比較,prinltn自帶換行,也可以當做結束標志。
而socket.shutdownOutput()雖然沒有關閉該Socket對象但是不能后續用該Socket對象傳輸發送數據了,必須關閉后重新new一個新的Socket。
2.Socket關閉問題
之前寫了個Socket做監聽代理,用Executor起了線程池接收Socket請求,當時服務端的用 socket = serverSocket.accept() 得到的socket在用完后沒有關閉,只在客戶端使用Socket時關閉了,程序部署上去一段時間,發現服務器上這個端口狀態都是CLOSE_WAIT,
一直占滿線程保持CLOSE_WAIT狀態導致后續Socket客戶端沒法再“被接收”。后來在服務端加了一行代碼,使用結束后服務端也關閉Socket對象。之后再測試,就是TIME_WAIT狀態了,過段時間自己就關閉了。
PS:以前一直以為客戶端和服務端Socket用的是一條通信“線”路,就像打電話一樣,A(客戶端)和B(服務端)通話,A主動掛斷了,B肯定也“被動”掛斷了,其實不是這樣的;真實情況是A主動掛斷了,B肯定也會保持打電話的姿態。
3. ServerSocket.setReuseAddress(true) 啟動端口重用,這行代碼一定要放到綁定端口前。
serverSocket =new ServerSocket(); serverSocket.setReuseAddress(true);//這個設置要放在綁定端口前 serverSocket.bind(new InetSocketAddress(serverPort)); pool = Executors.newFixedThreadPool(poolNum); logger.info("啟動監聽端口:"+serverPort); while(true){ socket = serverSocket.accept(); pool.execute(new HandleSocketSer(socket)); }
4.多線程Socket方案
Threadpool ---java自帶
Executor ---java自帶
ForkJoin ---java8自帶
Actor模型 ---scala庫自帶