欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

菜鳥初學(xué)Java的備忘錄(六)(轉(zhuǎn))-創(chuàng)新互聯(lián)

菜鳥初學(xué)Java的備忘錄(六) (轉(zhuǎn))[@more@]

2003年1月21日 星期二 晴
通過程序建立了實(shí)際的概念之后,現(xiàn)在應(yīng)該回到最開始的問題,Socket是什么?是實(shí)現(xiàn)計(jì)算機(jī)通信的一種方式,這毫無疑問.但如何能夠用最容易理解的語言比較形象而又不偏頗的描述它的原理呢?

站在用戶的角度思考問題,與客戶深入溝通,找到秀峰網(wǎng)站設(shè)計(jì)與秀峰網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都做網(wǎng)站、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋秀峰地區(qū)。

Bruce Eckel 在他的《Java 編程思想》一書中這樣描述套接字:
套接字是一種軟件抽象,用于表達(dá)兩臺(tái)機(jī)器之間的連接“終端”。對于一個(gè)給定的連接,每臺(tái)機(jī)器上都有一個(gè)套接字,您也可以想象它們之間有一條虛擬的“電纜”,“電纜”的每一端都插入到套接字中。當(dāng)然,機(jī)器之間的物理硬件和電纜連接都是完全未知的。抽象的全部目的是使我們無須知道不必知道的細(xì)節(jié).

 
按我的理解,抽象點(diǎn)來說,一個(gè)Socket就是一個(gè)電話聽筒,你有一個(gè),和你通話的人也有一個(gè),只不過其中有一個(gè)人的聽筒叫ServerSocket,另一個(gè)人的聽筒叫Socket.至于誰是ServerSocket,誰是Socket,這不重要,因?yàn)榭蛻舳撕头?wù)器端本來就是相對的,可以互相轉(zhuǎn)化的.通話的兩個(gè)人通過拿起兩個(gè)聽筒建立了一條通道,這條通道通不通就要看是不是雙方都拿起聽筒了,假如只有一方拿起聽筒,那就只能聽到一些嘟嘟的聲音,證明通道不同.這里,拿起聽筒的過程就是Socket初始化的過程.建立了通道之后,也就是大家都拿起聽筒之后,通道兩端的人就可以開始通話了.這里又有兩個(gè)過程,即A對B說話,B接聽,和B對A說話,A收聽,這兩個(gè)過程是通過兩條線路完成的.傳輸在這兩條線路上的,就是流.流隱藏了所有傳輸?shù)募?xì)節(jié),使得通信雙方都認(rèn)為,他們傳過去的是聲音,而不是編碼.


前面寫的服務(wù)器端的程序?qū)嶋H上是單任務(wù)版本,服務(wù)器對客戶機(jī)的處理機(jī)制是在同一時(shí)間段內(nèi)只能處理一個(gè)連接,因?yàn)閔andleConnection中采取的是不斷循環(huán)的阻塞方法,檢測到一個(gè),就處理一個(gè),然后再檢測到一個(gè),就再處理一個(gè),如果有多個(gè)連接同時(shí)請求,那只能排隊(duì)等候.這樣的程序是無法在網(wǎng)絡(luò)中應(yīng)付多個(gè)連接的,因?yàn)槟銦o法保證在同一時(shí)間內(nèi)只有一個(gè)客戶提出與服務(wù)器的連接請求,而用阻塞的方法應(yīng)付多客戶連接其速度之慢是可想而知的.

這樣就催生了面向多連接的版本.顯然,通過多線程可以來實(shí)現(xiàn)我們的要求.

由于要解決的是處理客戶連接的問題,因此我們的工作只是在服務(wù)器端的程序當(dāng)中修改.其原理不難推出,就是在檢測到一個(gè)連接請求之后,馬上建立一個(gè)線程去處理它,然后繼續(xù)兼聽下一個(gè)連接請求.所以,我們只需要將原來在handleConnection中的代碼原封不動(dòng)的放到線程的執(zhí)行代碼中,而在handleConnection中添加上新建線程的代碼就可以了,十分簡單.

同上一篇的風(fēng)格一樣,我們來觀察各個(gè)部分的代碼細(xì)節(jié).
首先為這個(gè)多線程的版本創(chuàng)建類MultiThreadRemoteFileServer

看看這個(gè)類的定義
import java.io.*;
import java.NET.*;

public class MultiThreadRemoteFileServer{
  protected int listenPort;
  public MultiThreadRemoteFileServer(int aListenPort){
  }
  public static void main(String[] args) {
  }
  public void acceptConnections() {
  }
  public void handleConnection(Socket incomingConnection) {
  }
}

幾乎和RemoteFileServer是一樣的,唯一的區(qū)別是在我們現(xiàn)在創(chuàng)建的這個(gè)類中增加了一個(gè)構(gòu)造函數(shù),這是為了能夠使得監(jiān)聽的端口號(hào)由我們自己來定.定義如下

public MultithreadedRemoteFileServer(int aListenPort) {
  listenPort = aListenPort;
}


先來看main()
public static void main(String[] args) {
  MultithreadedRemoteFileServer server = new MultithreadedRemoteFileServer(3000);
  server.acceptConnections();
}

沒有區(qū)別吧,和RemoteFileServer的main()函數(shù),只是端口號(hào)在創(chuàng)建的時(shí)候由主程序指定而已。

我們主要關(guān)心的改動(dòng)都在后面
現(xiàn)在看acceptConnection監(jiān)聽程序
public void acceptConnections() {
  try {
  ServerSocket server = new ServerSocket(listenPort, 5);//注意到?jīng)]有,建立服務(wù)器Socket的時(shí)候多了一個(gè)參數(shù),這個(gè)參數(shù)是用來指定能夠同時(shí)申請連接的大數(shù)目,缺省值是50
  Socket incomingConnection = null;
  while (true) {
  incomingConnection = server.accept();
  handleConnection(incomingConnection);
  }
  } catch (BindException e) {
  System.out.println("Unable to bind to port " + listenPort);
  } catch (IOException e) {
  System.out.println("Unable to instantiate a ServerSocket on port: " + listenPort);
  }
}

改動(dòng)的地方就一個(gè),多了個(gè)參數(shù).這里是它的工作機(jī)制。假設(shè)我們指定待發(fā)數(shù)(backlog 值)是5并且有五臺(tái)客戶機(jī)請求連接到我們的服務(wù)器。我們的服務(wù)器將著手處理第一個(gè)連接,但處理該連接需要很長時(shí)間。由于我們的待發(fā)值是 5,所以我們一次可以放五個(gè)請求到隊(duì)列中。我們正在處理一個(gè),所以這意味著還有其它五個(gè)正在等待。等待的和正在處理的一共有六個(gè)。當(dāng)我們的服務(wù)器仍忙于接受一號(hào)連接(記住隊(duì)列中還有 2—6 號(hào))時(shí),如果有第七個(gè)客戶機(jī)提出連接申請,那么,該第七個(gè)客戶機(jī)將遭到拒絕


接著看,我們的下一個(gè)改動(dòng)顯然是在處理監(jiān)聽到的線程的方法handleConnection中,前面已經(jīng)說了,在多線程的版本中,我們檢測到一個(gè)連接請求,就馬上生成一個(gè)線程,然后就不用理它了,那么在這里就是新建線程的一句話.

public void handleConnection(Socket connectionToHandle) {
  new Thread(new ConnectionHandler(connectionToHandle)).start();
}

我們注意到有一個(gè)新的類ConnectionHandler,這個(gè)類是Runnable的,即是一個(gè)接口類(這是用接口實(shí)現(xiàn)的一個(gè)線程,要是有不明白的話,可以去看看17號(hào)的關(guān)于線程的東西).我們用 ConnectionHandler 創(chuàng)建一個(gè)新 Thread 并啟動(dòng)它。正如我們剛才所說的,原來在RemoteFileServer的handleConnection中的代碼統(tǒng)統(tǒng)原封不動(dòng)的轉(zhuǎn)移到了這個(gè)接口類ConnectionHandler的run()方法中來了.

那么我們來看看整個(gè)ConnectionHandler類的定義吧。

class ConnectionHandler implements Runnable {
  protected Socket socketToHandle;
  public ConnectionHandler(Socket aSocketToHandle) {
  socketToHandle = aSocketToHandle;//通過構(gòu)造函數(shù),將待處理的Socket實(shí)例作為參數(shù)傳送進(jìn)來
  }
  public void run() {//原來對Socket的讀/寫的代碼都在這里了
  try {
  PrintWriter streamWriter = new PrintWriter(socketToHandle.getOutputStream());
  BufferedReader streamReader = new BufferedReader(new InputStreamReader(socketToHandle.getInputStream()));

  String fileToRead = streamReader.readLine();
  BufferedReader fileReader = new BufferedReader(new FileReader(fileToRead));

  String line = null;
  while ((line = fileReader.readLine()) != null)
  streamWriter.println(line);

  fileReader.close();
  streamWriter.close();
  streamReader.close();
  } catch (Exception e) {
  System.out.println("Error handling a client: " + e);
  }
  }
}


ConnectionHandler 的 run() 方法所做的事情就是 RemoteFileServer 上的 handleConnection() 所做的事情。首先把 InputStream 和 OutputStream 分別包裝(用 Socket 的 getOutputStream() 和 getInputStream())進(jìn) BufferedReader 和 PrintWriter。然后我們用這些代碼逐行地讀目標(biāo)文件.由于InputStream中裝的是文件路徑,所以中間還需要使用FileReader流將文件路徑包裝,再經(jīng)由BufferedReader包裝讀出.


我們的多線程服務(wù)器研究完了,同樣,我們回顧一下創(chuàng)建和使用“多線程版”的服務(wù)器的步驟:

1.修改 acceptConnections() 以用缺省為 50(或任何您想要的大于 1 的指定數(shù)字)實(shí)例化 ServerSocket。

2. 修改 ServerSocket 的 handleConnection() 以用 ConnectionHandler 的一個(gè)實(shí)例生成一個(gè)新的 Thread。

3.借用 RemoteFileServer 的 handleConnection() 方法的代碼實(shí)現(xiàn) ConnectionHandler 類的run()函數(shù)。


網(wǎng)頁名稱:菜鳥初學(xué)Java的備忘錄(六)(轉(zhuǎn))-創(chuàng)新互聯(lián)
URL地址:http://aaarwkj.com/article44/gjehe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標(biāo)簽優(yōu)化、做網(wǎng)站網(wǎng)站設(shè)計(jì)、網(wǎng)站策劃、移動(dòng)網(wǎng)站建設(shè)企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)
日韩av在线黄色免费大全| 男男啪啪猛进猛出无遮挡| 五月激情开心久久婷婷| 久久精品国产亚洲av清纯| 黄色片在线观看中文字幕| 久久亚洲综合色一区二区三区| 少妇毛片一区二区三区| 国产黄色片网站在线观看| 国产尹人99大香蕉| 中文字幕日韩欧美一区二区| 日韩一区二区三精品| 亚洲欧美日韩激情另类| 偷窥偷拍原味一区二区三区| 蜜臀av人妻一区二区三区| 变态另类日韩欧美高清| 亚洲欧美日韩香蕉在线观看| 97免费人妻在线视频| 久久亚洲精品1区2区| 亚洲福利一区福利三区| 91蜜臀视频在线播放| 一区二区亚洲免费的视频| 亚洲av在线视频免费播放| 国产成人精品亚洲av无人区| 欧美日韩亚洲精品综合网| 日韩欧美一区二区三区不卡在线| 日本东京热加勒比视频| 国产乱码精品一区二区蜜臀| 婷婷国产成人久久精品激情| 午夜视频在线观看黄片| 国产亚洲精品国产福利久久| 在线一区二区三区高清视频| 人妻中文字幕在线一二区| 亚洲欧美日韩一区中文字幕| 亚洲中文字幕av天堂久久| 日韩欧美一区二区中文字幕视频| 亚洲图文一区二区三区四区 | 97全国免费观看视频| 欧美精品三级不卡在线| 欧美一区二区三区有限公司| 日韩欧美亚洲自拍另类| 成人精品欧美欧美一级乱黄|