本文介紹如何用Java實現Socket編程。首先介紹Java針對Socket編程提供的類,以及它們之間的關係。而後分別針對TCP和UDP兩種傳輸層協議實現Socket編程。html
Java爲Socket編程封裝了幾個重要的類。前端
Socket類實現了一個客戶端socket,做爲兩臺機器通訊的終端,默認採用的傳輸層協議爲TCP,是一個可靠傳輸的協議。Socket類除了構造函數返回一個socket外,還提供了connect, getOutputStream, getInputStream和close方法。connect方法用於請求一個socket鏈接,getOutputStream用於得到寫socket的輸出流,getInputStream用於得到讀socket的輸入流,close方法用於關閉一個流。java
DatagramSocket類實現了一個發送和接收數據報的socket,傳輸層協議使用UDP,不能保證數據報的可靠傳輸。DataGramSocket主要有send, receive和close三個方法。send用於發送一個數據報,Java提供了DatagramPacket對象用來表達一個數據報。receive用於接收一個數據報,調用該方法後,一直阻塞接收到直到數據報或者超時。close是關閉一個socket。python
ServerSocket類實現了一個服務器socket,一個服務器socket等待客戶端網絡請求,而後基於這些請求執行操做,並返回給請求者一個結果。ServerSocket提供了bind、accept和close三個方法。bind方法爲ServerSocket綁定一個IP地址和端口,並開始監聽該端口。accept方法爲ServerSocket接受請求並返回一個Socket對象,accept方法調用後,將一直阻塞直到有請求到達。close方法關閉一個ServerSocket對象。程序員
SocketAddress提供了一個socket地址,不關心傳輸層協議。這是一個虛類,由子類來具體實現功能、綁定傳輸協議。它提供了一個不可變的對象,被socket用來綁定、鏈接或者返回數值。面試
InetSocketAddress實現了IP地址的SocketAddress,也就是有IP地址和端口號表達Socket地址。若是不制定具體的IP地址和端口號,那麼IP地址默認爲本機地址,端口號隨機選擇一個。編程
DatagramSocket是面向數據報socket通訊的一個可選通道。數據報通道不是對網絡數據報socket通訊的徹底抽象。socket通訊的控制由DatagramSocket對象實現。DatagramPacket須要與DatagramSocket配合使用才能完成基於數據報的socket通訊。跨域
上面描述了Java對Socket編程提供的接口,本節介紹如何實現一個基於TCP鏈接的Socket通訊。服務器
下面例子是Server端等待從Client端接收一條消息,而後再給客戶端發送一個消息。微信
服務器端首先實例化ServerSocket對象,而後爲其綁定一個本機地址,並開始監聽。一直阻塞狀態下等待客戶端請求,當得到客戶端鏈接請求後,返回一個socket對象。而後用這個socket接收一條消息,併發送一條消息。代碼以下:
package server.socket.java; import java.io.IOException; import java.io.PrintWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; public class SocketTcp { static private String TAG = "SocketTcp: "; public static void main(String[] args){ try { ServerSocket server = new ServerSocket(); SocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 10001); server.bind(address); System.out.println("==waiting for being connected..."); Socket client = server.accept(); System.out.println("==connected with " + client.getRemoteSocketAddress() ); PrintWriter socketOut = new PrintWriter(client.getOutputStream()); System.out.println("==waiting message from client..."); byte buf[] = new byte[1024]; if ( client.getInputStream().read(buf) > 0 ) { System.out.println("Receive Message: " + new String(buf)); } System.out.println("==sending message to client..."); String sendStr = "This is the message for client."; socketOut.write(sendStr); socketOut.flush(); socketOut.close(); client.close(); server.close(); } catch (IOException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } } }
客戶端首先實例化一個socket對象,用這個對象鏈接服務器端。鏈接成功後,發送一條消息,而後等待接收一條消息。代碼以下:
package client.socket.java; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; public class SocketTcp { static private String TAG = "SocketTcp: "; public static void main(String[] args){ try { final Socket socket = new Socket(); SocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 10001); System.out.println("==connecting to server ..."); socket.connect(address); PrintWriter socketOut = new PrintWriter(socket.getOutputStream()); BufferedReader socketIn = new BufferedReader( new InputStreamReader(socket.getInputStream()) ); String sendStr = "This is the message for server."; System.out.println("==sending message to server ..."); socketOut.write(sendStr); socketOut.flush(); System.out.println("==waiting message from server ..."); String receiveStr = socketIn.readLine(); System.out.println("Receive Message: " + receiveStr); socketOut.close(); socketIn.close(); socket.close(); } catch (IOException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } finally { } } }
服務器端運行結果:
==waiting for being connected... ==connected with /172.26.176.69:53912 ==waiting message from client... Receive Message: This is the message for server.
客戶端運行結果:
==connecting to server ... ==sending message to server ... ==waiting message from server ... Receive Message: This is the message for client.
基於UDP的Socket編程與基於TCP的socket編程稍有不一樣,socket server和client都用DatagramSocket實現。
下面例子是Server端等待從Client端接收一條消息,而後再給客戶端發送一個消息。
服務器端首先實例化DatagramSocket對象,而後爲其綁定一個本機地址,並開始監聽。一直阻塞狀態下等待從客戶端接收數據報。而後從數據報中獲取數據報的源地址,而後用這個源地址做爲目的地址打包一個數據報,而後發送出去。代碼以下:
package server.socket.java; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketException; import java.net.UnknownHostException; public class SocketUdp { final private static String TAG = "SocketUdp: "; public static void main(String args[]) { DatagramSocket socket = null; DatagramPacket datapacket = null; InetSocketAddress address = null; try { address = new InetSocketAddress(InetAddress.getLocalHost(), 7778); socket = new DatagramSocket(address); // socket.bind(address); byte buf[] = new byte[1024]; datapacket = new DatagramPacket(buf, buf.length); System.out.println("==block for receive messages..."); socket.receive(datapacket); buf = datapacket.getData(); InetAddress addr = datapacket.getAddress(); int port = datapacket.getPort(); System.out.println("Message Content: " + new String(buf) ); System.out.println("Receive From " + addr + ":" + port); SocketAddress toAddress = datapacket.getSocketAddress(); String sendStr = "I'm Server, this is the message for client."; buf = sendStr.getBytes(); datapacket = new DatagramPacket(buf, buf.length); datapacket.setSocketAddress(toAddress); socket.send(datapacket); System.out.println("==message sended"); } catch (UnknownHostException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } catch (SocketException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } catch (IOException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } } }
客戶端首先實例化一個DatagramSocket對象。利用服務器地址和端口號做爲目的地址打包一個數據報,併發送。而後等待從服務器回覆的數據報。代碼以下:
package client.socket.java; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketException; import java.net.UnknownHostException; public class SocketUdp { final private static String TAG = "SocketUdp: "; public static void main(String args[]) { try { DatagramSocket getSocket = new DatagramSocket(); DatagramPacket datapacket = null; InetSocketAddress toAddress = new InetSocketAddress(InetAddress.getLocalHost(), 7778); String sendStr = "I'm client, this is the message for server."; byte buf[] = sendStr.getBytes(); datapacket = new DatagramPacket(buf, buf.length); datapacket.setSocketAddress(toAddress); getSocket.send(datapacket); System.out.println("==message sended"); System.out.println("==block for receive messages..."); getSocket.receive(datapacket); buf = datapacket.getData(); System.out.println("Message Content: " + new String(buf)); } catch (SocketException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } catch (UnknownHostException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } catch (IOException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } } }
服務器端運行結果:
==block for receive messages... Message Content: I'm client, this is the message for server.
客戶端運行結果:
==message sended ==block for receive messages... Message Content: I'm Server, this is the message for client.
0
0
« 上一篇:傳輸層中的TCP和UDP淺析
» 下一篇:長鏈接與短鏈接
posted on 2013-09-02 00:56 洪雁君 閱讀(4109) 評論(0) 編輯 收藏
註冊用戶登陸後才能發表評論,請 登陸 或 註冊,訪問網站首頁。
【推薦】50萬行VC++源碼: 大型組態工控、電力仿真CAD與GIS源碼庫
【活動】阿里雲雙11活動開始預熱 雲服務器限時2折起
【調查】有獎調研即刻參與,你居然是醬紫程序猿!
【推薦】Vue.js 2.x 快速入門,大量高效實戰示例
最新IT新聞:
· 《周鴻禕自傳》書摘:首談私有化,我從沒想過退出
· 一個老外的自述:「在中國手機就是個人生命」
· PayPal CEO:將來5年內 金融科技變化將遠超過去30年
· 快遞員迴應"月薪過萬":送1件提成1元 雙11可掙萬元
· 微軟收購動態圖片應用程序Swng 團隊加入Skype部門
» 更多新聞...
最新知識庫文章:
· 關於編程,你的練習是否是有效的?
· 改善程序員生活質量的 3+10 習慣
· NASA的10條代碼編寫原則
· 爲何你參加了那麼多培訓,卻依然表現平平?
· 寫給初學前端工程師的一封信
Powered by:
博客園
Copyright © 洪雁君
|
||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|---|---|---|---|---|---|
29 | 30 | 31 | 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |