【正文】
} catch( IOException ie ) { ( ie )。 dout = new DataOutputStream( () )。 // Let39。 // ... The Constructor: Connect to the server: // Connect to the server try { // Initiate the connection socket = new Socket( host, port )。 // We want to receive messages when someone types a line // and hits return, using an anonymous class as // a callback ( new ActionListener() { public void actionPerformed( ActionEvent e ) { processMessage( () )。 add( North, tf )。 這并不是必須的 客戶端是一個(gè)獨(dú)立的應(yīng)用程序,向服務(wù)器端一樣,我們將不會(huì)再進(jìn)行更多的和前面一樣的討論。 *用戶用 DataInputStream 接收信息 客戶端的類: 不管怎么樣,我們已經(jīng)建立了我們聊天系統(tǒng)的服務(wù)器端,我們 有一個(gè)服務(wù)器對象監(jiān)聽到來的連接,和一堆處理自身的連接。你可以確定一個(gè)整形的數(shù)據(jù)被寫到 DataOutputStream 中并且這個(gè)整形數(shù)據(jù)可以從另外一端的 DataInputStream 讀出來。 Java 語言有一對非常有用的類 datainputstream 和 dataoutputstream 。 我們將建立自己的協(xié)議,因?yàn)檫@對于 java 語言來說是很簡單的。協(xié)議是如此的簡單幾乎不值得命名。 } 既然我們到了要討論用戶的時(shí)候了, 我們應(yīng)該說一下我們的通信協(xié)議。 = socket。 public class ServerThread extends Thread { // ... } Socket 對象是必不可少的,因?yàn)榫€程的目的是用 socket 來讓通信的雙方進(jìn)行通信的??梢酝ㄟ^ 來查詢。實(shí)際上,多線程讓我們彼此之間盡可能的迅速。多線程的優(yōu)點(diǎn)是:當(dāng)一個(gè)線程等待用戶緩慢發(fā)送消息時(shí),他基本上是處于休眠狀態(tài),直到那個(gè)用戶發(fā)送消息。而我們又不知道誰先發(fā)送消息,如果使用單線程,只有等到 0 號用戶先發(fā)送消息然后才輪到 1 號到 10 的用戶發(fā)送。 為什么要使用多線程? 詳細(xì)討論多線程超出了補(bǔ)習(xí)的范圍,雖然你在程序中使用線程的原因不只一個(gè),但最重要的原因是是要建造一個(gè)輸入輸出的聊天服務(wù)器。 除了多線程是在一個(gè)程序里共享數(shù)據(jù)資源以外,它類似任務(wù)和多任務(wù)處理的概念。但是 java 用來提供這些功能非常優(yōu)雅,特別是作為一種商業(yè)語言。 什么是 thread? Java 語言的兩個(gè)主要優(yōu)勢是網(wǎng)絡(luò)和多線程。 }} 代碼的最后一行創(chuàng)建了一個(gè)線程處理新的連接。t need to make it again ( s, dout )。 // Create a DataOutputStream for writing data to the // other side DataOutputStream dout = new DataOutputStream( () )。 // Tell the world we39。re ready to go ( Listening on +ss )。下面它們將做一些有用的東西,讓我們看看: private void listen( int port ) throws IOException { // Create the ServerSocket ss = new ServerSocket( port )。如果建立線程的速度夠快,連接將不會(huì)被阻塞。 但是對我們來說系列化已經(jīng)不是一個(gè)問題,因?yàn)槊看芜B接到來的時(shí)候,我們將建立一個(gè)新的線程來處理它。 一般來說,系列化是一個(gè)有效處理事情同時(shí)發(fā)生的一個(gè)有效的方法,但是它的一個(gè)潛在的缺點(diǎn)是消除了排比,也就是說,串行化阻止了我們在同一時(shí)間做很多的事情。 12 // loop forever while (true) { // get a connection Socket newSocket = ()。 Socket 暗含了一個(gè)簡單直接的處理方法:它串行接受連接,正如你一個(gè)挨一個(gè)的問他們一樣,而它們專門在排著隊(duì)等待。 接受 socket 可能你服務(wù)器程序是為了服務(wù)來自互聯(lián)網(wǎng)上的很多客戶端,這些客戶端將彼此不相關(guān)的與你的服務(wù)器建立連接,也就是說我們不能控制客戶端連接到來的時(shí)間和順序,下面我們將介紹多線程一個(gè)比較優(yōu)越的方法處理這些連接不管他們什么時(shí)候到來。 一個(gè)客戶端從定義,啟動(dòng)到連接服務(wù)器,我們是怎么得到這個(gè) socket 的呢?服務(wù)器端首先要做的工作是等待連接的建立,也就是說我們需要發(fā)送一些信息到客戶端,代表著連接的建立。 我們已經(jīng)準(zhǔn)備從我們的客戶接受連接,這就是說料體內(nèi)是如何進(jìn)行的。 // Create a Server object, which will automatically begin // accepting connections. new Server( port )。} Main() 方法例程: 11 Server 類要作為一個(gè)單獨(dú)的應(yīng)用程序,它必須包含一個(gè) main()方法,在你有了 main() 方法后,你可以添加你自己的基本應(yīng)用服務(wù)器代碼,這就是我們的服務(wù)器我們要完成的目的。這就告訴我們當(dāng)我們開始準(zhǔn)備接受連接的時(shí)候那些端口 是怎么監(jiān)聽的。 現(xiàn)在然我們開始介紹七個(gè)類中的一個(gè),監(jiān)聽類 下面的幾個(gè)版面我們來介紹這個(gè)類的基本的元素:構(gòu)造器和 main()實(shí)例。 套接字 : 客戶機(jī)和服務(wù)器之間的通信是通過建立一個(gè)叫做 socket 的對象來完成的, socket 是直接來自網(wǎng)絡(luò)編程,在 java 編程中,一個(gè) socket 對象被程序員使用多年,因?yàn)樗容^清晰的比較方便,也許這就是 java 比 c 語言方便的原因吧。 監(jiān)聽一個(gè)端口 : 首先,我們必須要做的是做好準(zhǔn)備接受連接,要做好這一點(diǎn),我們必須要監(jiān)聽一個(gè)端口, 一個(gè)端口被看作單獨(dú)一個(gè)計(jì)算機(jī)的地址, 往往是一個(gè)單一的機(jī)器,可作為網(wǎng)絡(luò)服務(wù)器,聊天服務(wù)器 FTP 服務(wù)器,和幾種服務(wù)器 一樣, 正因?yàn)槿绱?,一個(gè)連接到一臺(tái)服務(wù)器,不僅需要指明地址,該機(jī)器本身,而且還 要指明服務(wù)器 。它會(huì)照顧所有聯(lián)網(wǎng)的責(zé)任,其自己的。更先進(jìn)的服務(wù)器系統(tǒng)往往嵌入服務(wù)器代碼在一個(gè)較大的范圍內(nèi)。這樣做有一定的順序排列的優(yōu)雅,因?yàn)樵谟脩暨B接服務(wù)器之前,服務(wù)器必須啟動(dòng)。當(dāng)然有很多提供網(wǎng)絡(luò)細(xì)節(jié)的系統(tǒng),在許多情況下,最好的真實(shí)世界的解決辦法是使用現(xiàn)有的架構(gòu),因?yàn)樗3L峁┝?有用的功能,如容錯(cuò),負(fù)載平衡。我們將創(chuàng)造一個(gè)剝離下來,面向連接服務(wù)器,學(xué)習(xí)的基本框架將幫助你在未來大量制造其他面向連接服務(wù)器。但是,也有許多不同的方式提供服務(wù),并有很多不同的方式來構(gòu)建通信服務(wù)。 我們還將研究一些關(guān)于此框架的局限性并探索規(guī)避它們。 在本教程中,你將建立一個(gè)簡單的,集中的,面向連接 Java 服務(wù)器 。 ,如果 我們涵蓋的課題如網(wǎng)絡(luò)和多線程不夠詳細(xì) ,將在以后列舉例子, 即使你有很少或沒有做這樣的 項(xiàng) 目 的 經(jīng)驗(yàn) 。 客戶機(jī) /服務(wù)器 的基本概念并不是那么復(fù)雜,這個(gè)概念的提出 你有一個(gè)單一的服務(wù)器試圖 在同一時(shí)刻 服務(wù)于許多客戶。要想解開web 的神秘,你必須 了解客戶機(jī) /服務(wù)器系統(tǒng),另一個(gè) 關(guān)于 計(jì)算 機(jī)的 充滿困惑的問題。雖然 java 解決傳統(tǒng)的單機(jī)編程問題非常有用的,但它解決網(wǎng)絡(luò)編程問題也是非常有用的。 9 // ... 企業(yè)即時(shí)通 Java 作為另外一種計(jì)算機(jī)編程語言,你可能會(huì)問為什么它是如此重要, 為什么它在計(jì)算機(jī)編程 方面 被宣傳為一項(xiàng)革命性的一步 。 // We want to receive messages when someone types a line // and hits return, using an anonymous class as // a callback ( new ActionListener() { public void actionPerformed( ActionEvent e ) { processMessage( () )。 add( North, tf )。re assuming that one of the reasons you39。t change, you can be sure that an integer written to a DataOutputStream will be properly read from the DataInputStream at the other end. So our protocol will be this: * When a user types something into their chat window, their message will be sent as a string through a DataOutputStream. * When the server receives a message, through a DataInputStream, it will send this same message to all users, again as a string through a DataOutputStream. * The users will use a DataInputStream to receive the message. The Client class: Believe it or not, we39。s very easy to do,and because there39。s a protocol. We39。ve gotten to the point where we39。 // Start up the thread start()。s the code:: // Constructor. public ServerThread( Server server, Socket socket ) { // Save the parameters = server。s not going to know that users 1 through 10 are talking like crazy. For this reason, we39。d want to use threads in your program, but there is one reason most pertinent to the construction of a chat server: input/output. Your chat server is municating (in a sense) with the users at the client. Users are usually much slo