套接字Socket的引入
為了能夠方便地開發網絡應用軟件,由美國伯克利大學在Unix上推出了一種應用程序訪問通信協議的操作系統調用socket(套接字)。
socket的出現使程序員可以很方便地訪問TCP/IP,從而開發各種網絡應用程序。隨着Unix的應用推廣,套接字在編寫網絡軟件中得到了極大的普及。后來,套接字又被引進了Windows等操作系統中。Java語言也引進了套接字編程模型。
什么是Socket?
Socket是連接運行在網絡上的兩個程序間的雙向通訊的端點。
使用Socket進行網絡通信的過程
服務器端程序將一個套接字綁定到一個特定的端口,並通過此套接字等待和監聽客戶的連接請求。
客戶端程序根據服務器程序所在的主機名和端口號發出連接請求。
如果一切正常,服務器接受連接請求。並獲得一個新的綁定到不同的端口地址的套接字。(不可能有兩個程序同時占用一個端口)。客戶端和服務器端通過讀寫套接字進行通信。
使用ServerSocket和Socket實現服務器端和客戶端的socket通信。
其中:左邊ServerSocket類的構造方法可以傳入一個端口值來構建對象。accept()方法監聽向這個socket的連接並接收連接。它將會阻塞直到連接被建立好。連接建立好后他會返回一個Socket對象。連接建立好后,服務器端和客戶端的輸入流和輸出流就互為彼此,即一端的輸出流是另一端的輸入流。
使用ServerSocket和Socket實現服務器和客戶端的Socket通信流程:
- 建立Socket連接
- 獲得輸入/輸出流
- 讀/寫數據
- 關閉輸入/輸出流
- 關閉Socket
測試客戶端與服務器通信過程
服務端程序:

客戶端程序:

先運行服務器端程序,在運行客戶端,可以看到,運行客戶端之后服務器端輸出“Connected Successfully!”,表明連接建立之后才會往下執行。之后可以在服務器和客戶端上進行輸入操作,另一端將會收到輸入的信息並輸出。
使用線程實現服務器與客戶端的雙向通信
用兩個線程,一個線程專門用於處理服務器端的讀,另一個線程專門用於處理服務器端的寫。客戶端同理。代碼如下,程序共有六個類。
服務器和其輸入輸出線程:



客戶端和其輸入輸出線程(其輸入輸出線程和服務器的完全一樣):



服務器端打印信息
Wait for Connect! Connect successfully! Wait for Connect! server --> hello client --> Hi
客戶端打印信息:
server --> hello
client --> Hi
多個客戶端的程序實驗
可以啟動多個客戶端,同時與服務器進行交互。這里還是采用上面MainServer和MainClient及其輸入輸出程序代碼。
這部分做實驗的時候需要使用命令行,因為Eclipse里面每次Run的時候會重新啟動程序,即想要Run第二個客戶端的時候總是先關閉第一個客戶端(因為它們運行的是同一個程序),這樣,即只能有一個客戶端存在。(或者你開多個Eclipse,多建幾個workspace就行)
在命令行運行的方法如下:
因為源文件帶有包名,所以編譯采用:
javac -d .源文件名.java
注意d和.之間有一個空格。
可以使用通配符編譯所有的源文件,即使用:
javac -d .*.java
編譯之后執行:
java 完整包名+類名
先啟動服務器端程序,之后新開命令行窗口啟動客戶端程序,結果如下:
一個客戶端時,客戶端與服務器端交互正常
經過實驗,發現在一個服務器多個客戶端的情況下,客戶端可以流暢地向服務器發送消息,但是當服務器發送消息時,就會出現問題,並不是每一個客戶端都能收到信息。如圖中,當服務器發一條信息時候,兩個客戶端都沒有收到,但是服務器再發一條時候時候,兩個客戶端各接收到一條信息。如圖所示:
兩個客戶端,一個服務器,交互出現異常
實現服務器支持多客戶機通信
服務器端的程序要為每一個與客戶機連接的socket建立一個線程,來解決通信通信問題。
服務器應該管理一個socket的集合。
既要完成一個功能完善的客戶端和服務器通信程序,代碼還是需要進一步完善的。(初學者還不知道怎么完善?)
參考資料:
http://www.cnblogs.com/mengdd/archive/2013/03/10/2952616.html