瘋狂java講義
① 瘋狂java講義:使用DatagramSocket發送、接收數據[2]
程序客戶端代碼也與此類似 客戶端採用循環不斷地讀取用戶鍵盤輸入 每當讀到用戶輸入內容後就將該內容封裝成DatagramPacket數據報 再將該數據報發送出去 接著把DatagramSocket中的數據讀入接收用的DatagramPacket中(實際上是讀入該DatagramPacket所封裝的位元組數組中) 客戶端代碼如下
程序清單 codes/ / /UdpClient java
public class UdpClient
{
//定義發送數據報的目的地
public static final int DEST_PORT = ;
public static final String DEST_IP = ;
//定義每個數據報的最大大小為 K
private static final int DATA_LEN = ;
//定義該客戶端使用的DatagramSocket
private DatagramSocket socket = null;
//定義接收網路數據的位元組數組
byte[] inBuff = new byte[DATA_LEN];
//以指定位元組數組創建准備接受數據的DatagramPacket對象
private DatagramPacket inPacket =
new DatagramPacket(inBuff inBuff length)
//定義一個用於發送的DatagramPacket對象
private DatagramPacket outPacket = null;
public void init()throws IOException
{
try
{
//創建一個客戶端DatagramSocket 使用隨機埠
socket = new DatagramSocket()
//初始化發送用的DatagramSocket 它包含一個長度為 的位元組數組
outPacket = new DatagramPacket(new byte[ ]
InetAddress getByName(DEST_IP) DEST_PORT)
//創建鍵盤輸入流
Scanner scan = new Scanner(System in)
//不斷讀取鍵盤輸入
while(scan hasNextLine())
{
//將鍵盤輸入的一行字元串轉換位元組數組
byte[] buff = scan nextLine() getBytes()
//設置發送用的DatagramPacket里的位元組數據
outPacket setData(buff)
//發送數據報
socket send(outPacket)
//讀取Socket中的數據 讀到的數據放在inPacket所封裝的位元組數組里
socket receive(inPacket)
System out println(new String(inBuff
inPacket getLength()))
}
}
//使用finally塊保證關閉資源
finally
{
if (socket != null)
{
socket close()
}
}
}
public static void main(String[] args)
throws IOException
{
new UdpClient() init()
}
}
上面程序的粗體字代碼同樣也是通過DatagramSocket發送 接收DatagramPacket的關鍵代碼 這些代碼與伺服器的代碼基本相似 而客戶端與伺服器端的唯一區別在於 伺服器所在IP地址 埠是固定的 所以客戶端可以直接將該數據報發送給伺服器 而伺服器則需要根據接收到的數據報來決定將 反饋 數據報的目的地
讀者可能會發現 使用DatagramSocket進行網路通信時 伺服器端無須 也無法保存每個客戶端的狀態 客戶端把數據報發送到伺服器後 完全有可能立即退出 但不管客戶端是否退出 伺服器無法知道客戶端的狀態
當使用UDP協議時 如果想讓一個客戶端發送的聊天信息可被轉發到其他所有客戶端則比較困難 可以考慮在伺服器使用Set來保存所有客戶端信息 每當接收到一個客戶端的數據報之後 程序檢查該數據報的源SocketAddress是否在Set集合中 如果不在就將該SocketAddress添加到該Set集合中 但這樣一來又涉及一個問題 可能有些客戶端發送一個數據報之後永久性地退出了程序 但伺服器端還將該客戶端的SocketAddress保存在Set集合中……總之 這種方式需要處理的問題比較多 編程比較煩瑣 幸好Java為UDP協議提供了MulticastSocket類 通過該類可以輕松實現多點廣播
返回目錄 瘋狂Java講義
編輯推薦
Java程序性能優化 讓你的Java程序更快 更穩定
新手學Java 編程
Java程序設計培訓視頻教程
lishixin/Article/program/Java/hx/201311/27260
② 瘋狂Java講義:使用Socket進行通信[2]
程序清單 codes/ / /Client java
public class Client
{
public static void main(String[] args)
throws IOException
{
Socket socket = new Socket( )
//將Socket對應的輸入流包裝成BufferedReader
BufferedReader br = new BufferedReader(
new InputStreamReader(socket getInputStream()))
//進行普通IO操作
String line = br readLine()
System out println( 來自伺服器的數據 + line)
//關閉輸入流 socket
br close()
socket close()
}
}
上面程序中粗體字代碼是使用ServerSocket和Socket建立網路連接的代碼 斜體字代碼是通過Socket獲取輸入流 輸出流進行通信的代碼 通過程序不難看出 一旦使用ServerSocket Socket建立網路連接之後 程序通過網路通信與普通IO並沒有太大的區別
先運行上面程序中的Server類 將看到伺服器一直處於等待狀態 因為伺服器使用了死循環來接受來自客戶端的請求 再運行Client類 將可看到程序輸出 來自伺服器的數據 您好 您收到了伺服器的新年祝福! 這表明客戶端和伺服器端通信成功
上面程序為了突出通過ServerSocket和Socket建立連接 並通過底層IO流進行通信的主題 程序沒有進行異常處理 也沒有使用finally塊來關閉資源
實際應用中 程序可能不想讓執行網路連接 讀取伺服器數據的進程一直阻塞 而是希望當網路連接 讀取操作超過合理時間之後 系統自動認為該操作失敗 這個合理時間就是超時時長 Socket對象提供了一個setSoTimeout(int timeout)來設置超時時長 如下的代碼片段所示
Socket s = new Socket( )
//設置 秒之後即認為超時
s setSoTimeout( )
當我們為Socket對象指定了超時時長之後 如果在使用Socket進行讀 寫操作完成之前已經超出了該時間限制 那麼這些方法就會拋出SocketTimeoutException異常 程序可以對該異常進行捕捉 並進行適當處理 如下代碼所示
try
{
//使用Scanner來讀取網路輸入流中的數據
Scanner scan = new Scanner(s getInputStream())
//讀取一行字元
String line = scan nextLine()
…
}
//捕捉SocketTimeoutException異常
catch(SocketTimeoutException ex)
{
//對異常進行處理
…
}
假設程序需要為Socket連接伺服器時指定超時時長 即經過指定時間後 如果該Socket還未連接到遠程伺服器 則系統認為該Socket連接超時 但Socket的所有構造器里都沒有提供指定超時時長的參數 所以程序應該先創建一個無連接的Socket 再調用Socket的connect()方法來連接遠程伺服器 而connect方法就可以接受一個超時時長參數 如下代碼所示
//創建一個無連接的Socket
Socket s = new Socket()
//讓該Socket連接到遠程伺服器 如果經過 秒還沒有連接到 則認為連接超時
s connconnect(new InetAddress(host port) )
返回目錄 瘋狂Java講義
編輯推薦
Java程序性能優化 讓你的Java程序更快 更穩定
新手學Java 編程
Java程序設計培訓視頻教程
lishixin/Article/program/Java/hx/201311/27265
③ 瘋狂java講義學完什麼水平
瘋狂java講義學完中等水平。瘋狂java講義是國人原創必讀經典了,同樣非常適合初學者。講解內容細致全面,系統通俗,目錄劃分和查找非常方便,就算完全沒有基礎也可以學的沒有什麼壓力,學完可以升級一個水平,達到中等水平。
④ 推薦幾本安卓開發的書籍,我學過一點點java,也算有點java基礎的
最好的java學習,最全的java學習
《瘋狂Java講義》---本書並不是一本簡單的Java入門教材,也不是一門「閉門造車」式的Java讀物。本書來自於筆者6年多的Java培訓經歷,凝結了筆者近6000個小時的授課經驗,總結了上千個Java學員學習過程中的典型錯誤。
《瘋狂Android講義》---本書全面地介紹了Android應用開發的相關知識。
《輕量級Java EE企業應用實戰--Struts 2+Spring+Hibernate整合開發》---本書是《輕量級Java EE企業應用實戰》的第3版,第3版保持了第2版內容全面、深入的特點,主要完成全部知識的升級。
《 瘋狂Java 突破程序員基本功16課》、《瘋狂XML講義》、《瘋狂Ajax講義Prototype/jQuery+DWR+Spring+Hibernate整合開發》、《Struts 2.1權威指南--基於WebWork核心的MVC開發》、《經典Java EE企業應用實戰》
《瘋狂HTML 5/CSS 3/JavaScript講義》 --- 本書是一本全面介紹HTML5、CSS 3和JavaScript前端開發技術的圖書,本書系統地介紹了HTML 5常用的元素和屬性,HTML 5的表單元素和屬性,HTML 5的繪圖支持,HTML 5的多媒體支持,CSS 3的功能和用法、包括最前沿的變形與動畫功能等。配合『瘋狂java』官網上的視頻學習。「李剛老師視頻」、「肖文吉老師視頻」「李韓飛老師視頻」
⑤ 瘋狂Java講義的源碼如何導入eclipse運行
Java項目的源代碼通過一下四部完成導入到eclipse
1、單擊eclipse的file菜單 ,選擇 import project from file system
2、在彈出的窗口單擊 diretory 按鈕 選擇Java源代碼文件系統所在的目錄
3、單擊「選擇文件夾 」完成將java源代碼導入到eclispe系統
你明白了嗎?
⑥ 瘋狂Java講義:使用MulticastSocket實現多點廣播(4)
該類主要實現底層的網路通信功能 在該類中提供了一個broadCast方法 該方法使用MulticastSocket將指定字元串廣播到所有客戶端 還提供了sendSingle方法 該方法使用DatagramSocket將指定字元串發送到指定SocketAddress 如程序中前兩行粗體字代碼所示 除此之外 該類里還提供了 個內部線程類 ReadSingle和ReadBroad 這兩個線程類採用循環不斷讀取DatagramSocket和MulticastSocket中的數據 如果讀到的信息是廣播來的在線信息 則保持該用戶在線 如果讀到的是用戶的聊天信息 則直接將該信息顯示出來
在該類中用到了本程序的一個主類 LanChat 該類使用DefaultListModel來維護用戶列表 該類里的每個列表項就是一個UserInfo 該類還提供了一個ImageCellRenderer 該類用於將列表項繪制出用戶圖標和用戶名字
程序清單 codes/ / /LanChat/LanChat java
public class LanChat extends JFrame
{
private DefaultListModel listModel = new DefaultListModel()
//定義一個JList對象
private JList friendsList = new JList(listModel)
//定義一個用於格式化日期的格式器
private DateFormat formatter = DateFormat getDateTimeInstance()
public LanChat()
{
super( 區域網聊天 )
//設置該JList使用ImageCellRenderer作為單元格繪制器
friendsList setCellRenderer(new ImageCellRenderer())
listModel addElement(new UserInfo( all 所有人 null ))
friendsList addMouseListener(new ChangeMusicListener())
add(new JScrollPane(friendsList))
setDefaultCloseOperation(JFrame EXIT_ON_CLOSE)
setBounds( )
}
//向用戶列表中添加用戶
public void addUser(UserInfo user)
{
listModel addElement(user)
}
//從用戶列表中刪除用戶
public void removeUser(int pos)
{
listModel removeElementAt(pos)
}
//根據地址來查詢用戶
public UserInfo getUserBySocketAddress(SocketAddress address)
{
for (int i = ; i < getUserNum() ; i++)
{
UserInfo user = getUser(i)
if (user getAddress() != null &&
user getAddress() equals(address))
{
return user;
}
}
return null;
}
// 下面兩個方法是對ListModel的包裝
//獲取該聊天窗口的用戶數量
public int getUserNum()
{
return listModel size()
}
//獲取指定位置的用戶
public UserInfo getUser(int pos)
{
return (UserInfo)listModel elementAt(pos)
}
//實現JList上的滑鼠雙擊監聽器
class ChangeMusicListener extends MouseAdapter
{
public void mouseClicked(MouseEvent e)
{
//如果滑鼠的擊鍵次數大於
if (e getClickCount() >= )
{
//取出滑鼠雙擊時選中的列表項
UserInfo user = (UserInfo)friendsList getSelectedValue()
//如果該列表項對應用戶的交談窗口為null
if (user getChatFrame() == null)
{
//為該用戶創建一個交談窗口 並讓該用戶引用該窗口
user setChatFrame(new ChatFrame(null user))
}
//如果該用戶的窗口沒有顯示 則讓該用戶的窗口顯示出來
if (!user getChatFrame() isShowing())
{
user getChatFrame() setVisible(true)
}
}
}
}
/**
* 處理網路數據報 該方法將根據聊天信息得到聊天者
* 並將信息顯示在聊天對話框中
* @param packet 需要處理的數據報
* @param single 該信息是否為私聊信息
*/
public void processMsg(DatagramPacket packet boolean single)
{
//獲取該發送該數據報的SocketAddress
InetSocketAddress srcAddress = (InetSocketAddress)packet getSocket
Address()
//如果是私聊信息 則該Packet獲取的是DatagramSocket的地址 將埠減 才是
//對應的MulticastSocket的地址
if (single)
{
srcAddress = new InetSocketAddress(srcAddress getHostName()
srcAddress getPort() )
}
UserInfo srcUser = getUserBySocketAddress(srcAddress)
if (srcUser != null)
{
//確定消息將要顯示到哪個用戶對應窗口上
UserInfo alertUser = single ? srcUser : getUser( )
//如果該用戶對應的窗口為空 顯示該窗口
if (alertUser getChatFrame() == null)
{
alertUser setChatFrame(new ChatFrame(null alertUser))
}
//定義添加的提示信息
String tipMsg = single ? 對您說 : 對大家說 ;
//顯示提示信息
alertUser getChatFrame() addString(srcUser getName() + tipMsg
+ ……( + formatter format(new Date()) + )
+ new String(packet getData() packet getLength()) + )
if (!alertUser getChatFrame() isShowing())
{
alertUser getChatFrame() setVisible(true)
}
}
}
//主方法 程序的入口
public static void main(String[] args)
{
LanChat lc = new LanChat()
new LoginFrame(lc 請輸入用戶名 頭像後登錄 )
}
}
//定義用於改變JList列表項外觀的類
class ImageCellRenderer extends JPanel implements ListCellRenderer
{
private ImageIcon icon;
private String name;
//定義繪制單元格時的背景色
private Color background;
//定義繪制單元格時的前景色
private Color foreground;
public Component getListCellRendererComponent(JList list Object value int
index boolean isSelected boolean cellHasFocus)
{
UserInfo userInfo = (UserInfo)value;
icon = new ImageIcon( ico/ + userInfo getIcon() + gif )
name = userInfo getName()
background = isSelected ? list getSelectionBackground() : list getBack
ground()
foreground = isSelected ? list getSelectionForeground() : list
getForeground()
//返回該JPanel對象作為單元格繪制器
return this;
}
//重寫paintComponent方法 改變JPanel的外觀
public void paintComponent(Graphics g)
{
int imageWidth = icon getImage() getWidth(null)
int imageHeight = icon getImage() getHeight(null)
g setColor(background)
g fillRect( getWidth() getHeight())
g setColor(foreground)
//繪制好友圖標
g drawImage(icon getImage() getWidth() / imageWidth / null)
g setFont(new Font( SansSerif Font BOLD ))
//繪制好友用戶名
g drawString(name getWidth() / name length() * imageHeight + )
}
//通過該方法來設置該ImageCellRenderer的最佳大小
public Dimension getPreferredSize()
{
return new Dimension( )
}
}
上面類中提供的addUser和removeUser方法用於暴露給通信類ComUtil使用 用於向用戶列表中添加 刪除用戶 除此之外 該類還提供了一個processMsg方法 該方法用於處理網路中讀取的數據報 將數據報中的內容取出 並顯示在特定的窗口中
上面講解的只是本程序的關鍵類 本程序還涉及YeekuProtocol ChatFrame LoginFrame等類 由於篇幅關系 此處不再給出這些類的源代碼 讀者可以參考codes/ / /LanTalk路徑下的源代碼
返回目錄 瘋狂Java講義
編輯推薦
Java程序性能優化 讓你的Java程序更快 更穩定
新手學Java 編程
lishixin/Article/program/Java/hx/201311/27255
⑦ 大家覺得初學者《瘋狂Java講義》怎麼樣
我見過特好的一本書,很值得買。全書大概有800頁,javase的知識都涉及到,部分內容對新手有難度,沒有編程基礎不建議看。而且也不適合只想過java二級的,只適合打算在java領域深造的人群。至於大神的話,不用看se的書了吧。