<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    神奇好望角 The Magical Cape of Good Hope

    庸人不必自擾,智者何需千慮?
    posts - 26, comments - 50, trackbacks - 0, articles - 11
      BlogJava :: 首頁(yè) ::  :: 聯(lián)系 :: 聚合  :: 管理

    前面已經(jīng)看到,Socket 類(lèi)的 getInputStream()getOutStream() 方法分別獲取套接字的輸入流和輸出流。輸入流用來(lái)讀取遠(yuǎn)端發(fā)送過(guò)來(lái)的數(shù)據(jù),輸出流則用來(lái)向遠(yuǎn)端發(fā)送數(shù)據(jù)。

    輸入流

    使用套接字的輸入流讀取數(shù)據(jù)時(shí),當(dāng)前線程會(huì)進(jìn)入阻塞狀態(tài),直到套接字收到一些數(shù)據(jù)為止(亦即套接字的接收緩沖區(qū)有可用數(shù)據(jù))。該輸入流的 available() 方法只是返回接收緩沖區(qū)的可用字節(jié)數(shù)量,不可能知道遠(yuǎn)端還要發(fā)送多少字節(jié)。使用輸入流的時(shí)候,最好先將它包裝為一個(gè) BufferedInputStream,因?yàn)樽x取接收緩沖區(qū)將導(dǎo)致 JVM 和底層系統(tǒng)之間的切換,應(yīng)當(dāng)盡量減少切換次數(shù)以提高性能。BufferedInputStream 的緩沖區(qū)大小最好設(shè)為套接字接收緩沖區(qū)的大小。

    如果直接調(diào)用輸入流的 close() 方法來(lái)關(guān)閉它,則將導(dǎo)致套接字被關(guān)閉。對(duì)此,Socket 類(lèi)提供了一個(gè) shutdownInput() 方法來(lái)禁用輸入流。調(diào)用該方法后,每次讀操作都將返回 EOF,無(wú)法再讀取遠(yuǎn)端發(fā)送的數(shù)據(jù)。對(duì)這個(gè) EOF 的檢測(cè),不同的輸入流包裝體現(xiàn)出不同的結(jié)果,可能讀到 -1 個(gè)字節(jié),可能讀到的字符串為 null,還可能收到一個(gè) EOFException 等等。禁用輸入流后,遠(yuǎn)端輸出流的行為是平臺(tái)相關(guān)的:

    • 在 BSD 平臺(tái)上,遠(yuǎn)端的發(fā)送的數(shù)據(jù)能正常接收,然后直接丟棄。遠(yuǎn)端無(wú)法知道本端的輸入流已禁用。這和 JDK 文檔描述的行為一致。
    • 在 WINSOCK 平臺(tái)上,遠(yuǎn)端發(fā)送數(shù)據(jù)將會(huì)導(dǎo)致“連接被重置”的錯(cuò)誤。
    • 在 Linux 平臺(tái)上,遠(yuǎn)端發(fā)送的數(shù)據(jù)能繼續(xù)接收,直到套接字輸入緩沖區(qū)填滿,之后遠(yuǎn)端再也無(wú)法發(fā)送數(shù)據(jù)(若使用阻塞模式則進(jìn)入死鎖)。

    禁用輸入流這種技術(shù)并不常用。

    輸出流

    套接字的輸出操作實(shí)際上僅僅將數(shù)據(jù)寫(xiě)到發(fā)送緩沖區(qū)內(nèi),當(dāng)發(fā)送緩沖區(qū)填滿且上次的發(fā)送成功后,由底層系統(tǒng)負(fù)責(zé)發(fā)送。如果發(fā)送緩沖區(qū)的剩余空間不夠,當(dāng)前線程就會(huì)阻塞。和輸入流類(lèi)似,最好將輸出流包裝為 BufferedOutputStream

    如果套接字的雙發(fā)都使用 ObjectInputStreamObjectOutputStream 來(lái)讀寫(xiě) Java 對(duì)象,則必須先創(chuàng)建 ObjectOutputStream,因?yàn)?ObjectInputStream 在構(gòu)造的時(shí)候會(huì)試圖讀取對(duì)象頭部,如果雙發(fā)都先創(chuàng)建 ObjectInputStream,則會(huì)互相等待對(duì)方的輸出,造成死鎖:

    // 創(chuàng)建的順序不能顛倒!
    ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
    ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        

    類(lèi)似于輸入流,關(guān)閉輸出流也導(dǎo)致關(guān)閉套接字,所以 Socket 類(lèi)同樣提供了一個(gè) shutdownOutput() 來(lái)禁用輸出流。禁用輸出流后,已寫(xiě)入發(fā)送緩沖區(qū)的數(shù)據(jù)會(huì)正常發(fā)送,之后的任何寫(xiě)操作都會(huì)導(dǎo)致 IOException,且遠(yuǎn)端的輸入流始終會(huì)讀到 EOF。禁用輸出流非常有用,例如套接字的雙發(fā)都在發(fā)送完畢數(shù)據(jù)后禁用輸入流,然后雙方都會(huì)收到 EOF,從而知道數(shù)據(jù)已經(jīng)全部交換完畢,可以安全關(guān)閉套接字。直接關(guān)閉套接字會(huì)同時(shí)關(guān)閉輸入流和輸出流,且斷開(kāi)連接,達(dá)不到這種效果。

    使用流的阻塞套接字的優(yōu)缺點(diǎn)

    如果要使用流進(jìn)行輸入和輸出,就只能用阻塞模式的套接字。這里總結(jié)一下阻塞套接字的優(yōu)缺點(diǎn)。先看看優(yōu)點(diǎn):

    1. 編程模型簡(jiǎn)單,非常適合初學(xué)者上手。
    2. 以裝飾器模式設(shè)計(jì)的 Java I/O 使得開(kāi)發(fā)人員可以輕松地從 I/O 流讀寫(xiě)任何類(lèi)型的數(shù)據(jù)。

    但在性能方面有致命的缺點(diǎn):

    1. 由于服務(wù)器套接字接受連接,以及套接字的讀寫(xiě)都會(huì)阻塞,性能低下。
    2. 如果不對(duì) I/O 流手動(dòng)進(jìn)行緩沖,則可能造成一次只處理一個(gè)字節(jié),性能低下。
    3. 服務(wù)器套接字每次只能接受一個(gè)連接,導(dǎo)致 JVM 和底層系統(tǒng)之間頻繁的調(diào)用切換,性能低下。

    下一篇文章開(kāi)始探討使用基于 NIO 的套接字通道和緩沖區(qū)實(shí)現(xiàn)伸縮性更強(qiáng)的 TCP 套接字。


    評(píng)論

    # 為什么用socket的getinputStream之后用bufferedreader包裝向遠(yuǎn)程發(fā)送數(shù)據(jù),只能發(fā)送一次,用flush()不行了,只能關(guān)閉輸出流才能接收到呢?[未登錄](méi)  回復(fù)  更多評(píng)論   

    2013-06-18 23:22 by 123
    socket的流問(wèn)題!
    主站蜘蛛池模板: 13小箩利洗澡无码视频网站免费| 亚洲av第一网站久章草| 亚欧洲精品在线视频免费观看 | 日韩视频在线免费| 亚洲熟女综合色一区二区三区| 久久ww精品w免费人成| 亚洲综合成人网在线观看| 日本免费污片中国特一级| 亚洲2022国产成人精品无码区| 国产永久免费高清在线| 无码久久精品国产亚洲Av影片| 免费无遮挡无码永久视频| 1区1区3区4区产品亚洲| 97国产免费全部免费观看| 亚洲精品综合在线影院| 国产麻豆免费观看91| 乱淫片免费影院观看| 色噜噜AV亚洲色一区二区| 久久精品电影免费动漫| 亚洲综合激情九月婷婷| 成年美女黄网站色大免费视频| 亚洲色欲色欲www在线播放| 四虎在线播放免费永久视频 | 亚洲国产精品免费视频| 国产高清不卡免费在线| 亚洲欧美日韩一区二区三区| 无码不卡亚洲成?人片| 中文字幕乱码一区二区免费| 亚洲视频免费一区| 免费观看a级毛片| 亚洲一级片免费看| 亚洲精品中文字幕乱码影院| 免费网站看v片在线香蕉| 精品熟女少妇aⅴ免费久久| 中文字幕亚洲综合精品一区| 在线A级毛片无码免费真人| 精精国产www视频在线观看免费| 久久综合亚洲色HEZYO社区| 四虎免费久久影院| 免费av片在线观看网站| 亚洲乱亚洲乱妇24p|