Socket又稱套接字,應用程序通常通過“套接字”向網絡發出請求或者應答網絡請求。
在Java中,Socket和ServerSocket類庫位於java.net包中。ServerSocket用於服務器端,Socket是建立網絡連接時使用的。在連接成功後,應用程序兩端都會產生一個Socket實例,操作這個實例,完成所需的對話。對於一個網絡連接來說,套接字是平等的,並沒有差別,不應爲在服務器端或者在客戶端而產生不同級別。不管是Socket還是ServerSocket它們的工作都是通過Socket類及其子類完成的。
Socket鏈接的建立過程:
-
服務器監聽(SocketServer監聽某個端口,阻塞線程,等待客戶端訪問這個端口,當有請求訪問該端口,解除阻塞,accept()方法返回一個socket對象)
-
客戶端發出請求(Socket(string ip, int port)客戶端創建socket對象,連接服務器該端口)
-
建立鏈接 (客戶端請求該端口,被服務器監聽到,兩個相對的socket相關聯)
-
通信(客戶端socket寫入信息到輸出流,則服務端的socket可以從輸入流中讀取,反則亦然)
Socket的特點:
-
Socket基於TCP協議,數據傳輸有保障
-
Socket適用於建立長時間鏈接
-
Socket編程通常應用於即時通訊
實例代碼:使用JFrame實現一個簡單聊天室
Eclipse安裝WindowBuilder插件,可以實現拖拽控件的形式生成swing代碼,
WindowBuilder插件安裝地址:http://www.eclipse.org/windowbuilder/download.php
-
Eclipse (Mars版):http://download.eclipse.org/windowbuilder/WB/release/R201506241200-1/4.5/
點擊Eclipse的功能欄的help-》install new software -》點擊add按鈕,填寫上方1的url到Location中,完成安裝。
客戶端核心代碼:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
public class ChatManager
{ private ChatManager(){} private static final ChatManager
instance = new ChatManager(); public static ChatManager
getCM() { return instance; } MainWIndow
window; Socket
socket; BufferedReader
reader; PrintWriter
writer; public void setWindow(MainWIndow
window) { this .window
= window; window.appendText( "文本框已經和ChatManager綁定了。" ); } public void connect(String
ip) { new Thread(){ @Override public void run()
{ try { socket
= new Socket(ip, 12345 ); writer
= new PrintWriter( new OutputStreamWriter( socket.getOutputStream())); reader
= new BufferedReader( new InputStreamReader( socket.getInputStream())); String
line; while ((line
= reader.readLine()) != null )
{ window.appendText( "收到:" +line); } writer.close(); reader.close(); writer
= null ; reader
= null ; } catch (UnknownHostException
e) { e.printStackTrace(); } catch (IOException
e) { e.printStackTrace(); } } }.start(); } public void send(String
out) { if (writer
!= null )
{ writer.write(out+ "\n" ); writer.flush(); } else { window.appendText( "當前的鏈接已經中斷" ); } } } |
服務器端核心代碼:
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
|
public class ChatManager
{ private ChatManager(){} private static final ChatManager
cm = new ChatManager(); public static ChatManager
getChatManager() { return cm; } Vector<ChatSocket>
vector = new Vector<ChatSocket>(); public void add(ChatSocket
cs) { vector.add(cs); } public void remove(ChatSocket
cs) { vector.remove(cs); } public void publish(ChatSocket
cs,String out) { for ( int i
= 0 ;
i < vector.size(); i++) { ChatSocket
csChatSocket = vector.get(i); if (!cs.equals(csChatSocket))
{ csChatSocket.out(out); } } } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class ServerListener extends Thread
{ @Override public void run()
{ try { ServerSocket
serverSocket = new ServerSocket( 12345 ); while ( true )
{ //block Socket
socket = serverSocket.accept(); ChatSocket
cs = new ChatSocket(socket); cs.start(); ChatManager.getChatManager().add(cs); } } catch (IOException
e) { e.printStackTrace(); } } } |