Socket又稱"套接字",網絡上的兩個程序經過一個雙向的通訊鏈接實現數據的交換,這個鏈接的一端稱爲一個socket。java
ServerSocket,此類實現服務器套接字。服務器套接字等待經過網絡傳入的請求而後基於該請求執行某些操做,可能向請求者返回結果。編程
Socket方法 getInetAddress(); //遠程服務端的IP地址 getPort(); //遠程服務端的端口 getLocalAddress() //本地客戶端的IP地址 getLocalPort() //本地客戶端的端口 getInputStream(); //得到輸入流 getOutStream(); //得到輸出流 Socket狀態 isClosed(); //鏈接是否已關閉,若關閉,返回true;不然返回false isConnect(); //若是曾經鏈接過,返回true;不然返回false isBound(); //若是Socket已經與本地一個端口綁定,返回true;不然返回false
說明:二者本質均是Socket間的通訊,一方爲客戶,另外一方爲服務器。客戶鏈接服務器,服務器接受客戶並生成一個與其交流的Socket,而後客戶發送請求,服務器作出響應。服務器
1.從套接字讀取信息時,在有數據可供訪問以前,讀操做會被阻塞。網絡
解決:對於不一樣的應用應該設置合理的超時值。app
socket.setSoTimeout(10000);
說明:設置超時值後,若是沒有在規定時間內接受到數據,就會拋出SocketTimeOutException異常。你能夠捕獲這個異常並作出反應。 socket
2.客戶端在鏈接到服務器以前會一直堵塞。ui
解決:能夠先構造一個無鏈接的套接字,而後再使用一個超時來進行鏈接的方法解決這個問題。spa
Socket socket = new Socket("127.0.0.1",12345); //用下面方法代替上面方法 Socket socket1 = new Socket(); socket1.connect(new InetSocketAddress("127.0.0.1",12345),timeout);
若是在客戶端,你須要寫下以下的代碼就能夠打開一個socket。.net
String host = "127.0.0.1"; int port = 8919; Socket client = new Socket(host, port);
上面代碼中,host即客戶端須要鏈接的機器,port就是服務器端用來監聽請求的端口。在選擇端口時,須要注意一點,就是0~1023這些端口都已經被系統預留了。這些端口爲一些經常使用的服務所使用,好比郵件,FTP和HTTP。當你在編寫服務器端的代碼,選擇端口時,請選擇一個大於1023的端口。server
接下來就是寫入請求數據,咱們從客戶端的socket對象中獲得OutputStream對象,而後寫入數據後。很相似文件IO的處理代碼。
public class ClientSocket { public static void main(String args[]) { String host = "127.0.0.1"; int port = 8919; try { Socket client = new Socket(host, port); Writer writer = new OutputStreamWriter(client.getOutputStream()); writer.write("Hello From Client"); writer.flush(); writer.close(); client.close(); } catch (IOException e) { e.printStackTrace(); } } }
相似文件IO,在讀寫數據完成後,咱們須要對IO對象進行關閉,以確保資源的正確釋放。
int port = 8919; ServerSocket server = new ServerSocket(port); Socket socket = server.accept();
上面的代碼建立了一個服務器端的socket,而後調用accept方法監聽並獲取客戶端的請求socket。accept方法是一個阻塞方法,在服務器端與客戶端之間創建聯繫以前會一直等待阻塞。
經過上面獲得的socket對象獲取InputStream對象,而後安裝文件IO同樣讀取數據便可。這裏咱們將內容打印出來。
public class ServerClient { public static void main(String[] args) { int port = 8919; try { ServerSocket server = new ServerSocket(port); Socket socket = server.accept(); Reader reader = new InputStreamReader(socket.getInputStream()); char chars[] = new char[1024]; int len; StringBuilder builder = new StringBuilder(); while ((len=reader.read(chars)) != -1) { builder.append(new String(chars, 0, len)); } System.out.println("Receive from client message=: " + builder); reader.close(); socket.close(); server.close(); } catch (Exception e) { e.printStackTrace(); } } }
仍是不能忘記的,最後須要正確地關閉IO對象,以確保資源的正確釋放。
進行客戶端-服務器端編程仍是比較有趣的,同時在Java中進行socket編程要比其餘語言(如C)要簡單快速編寫。java.net這個包裏面包含了不少強大靈活的類供開發者進行網絡編程,在進行網絡編程中,建議使用這個包下面的API。同時Sun.*這個包也包含了不少的網絡編程相關的類,可是不建議使用這個包下面的API,由於這個包可能會改變,另外這個包不能保證在全部的平臺都有包含。