A. 在javasocket網路編程中,開發基於udp協議的程序使用的套接字有哪些
一、 填空題
___ IP地址____用來標志網路中的一個通信實體的地址。通信實體可以是計算機,路由器等。
統一資源定位符URL是指向互聯網「資源」的指針,由4部分組成:協議、存放資源的主機域名、__埠___和資源路徑和文件名。
URL 是統一資源定位器的簡稱,它表示Internet上某一資源的地址。
在Socket編程中,IP地址用來標志一台計算機,但是一台計算機上可能提供多種應用程序,使用 埠 來區分這些應用程序。
在Java Socket網路編程中,開發基於TCP協議的伺服器端程序使用的套接字是 ServerSocket 。
在Java Socket網路編程中,開發基於UDP協議的程序使用的套接字是 DatagramSocket 。
二、 選擇題
1.以下協議都屬於TCP/IP協議棧,其中位於傳輸層的協議是(AD)。(選擇二項)
A TCP
B.HTTP
C.SMTP
D.UDP
2.以下協議中屬於TCP/IP協議棧中應用層協議的是(A)。(選擇一項)
A HTTP
B.TCP
C.UDP
D.IP
3.以下說法中關於UDP協議的說法正確的是(AD)。(選擇二項)
A.發送不管對方是否准備好,接收方收到也不確認
B.面向連接
C.佔用系統資源多、效率低
D.非常簡單的協議,可以廣播發送
4.在基於TCP網路通信模式中,客戶與伺服器程序的主要任務是(BC)。(選擇二項)
A 客戶程序在網路上找到一條到達伺服器的路由
B.客戶程序發送請求,並接收伺服器的響應
C.伺服器程序接收並處理客戶請求,然後向客戶發送響應結果
D.如果客戶程序和伺服器都會保證發送的數據不會在傳輸途中丟失
5.在Java網路編程中,使用客戶端套接字Socket創建對象時,需要指定(A)。(選擇一項)
A 伺服器主機名稱和埠
B.伺服器埠和文件
C.伺服器名稱和文件
D.伺服器地址和文件
6.ServerSocket的監聽方法accept( )方法的返回值類型是(A )。(選擇一項)
A.Socket
B.Void
C.Object
D.DatagramSocket
7.Java UDP Socket編程主要用到的兩個類是(BD)。(選擇二項)
A UDPSocket
B.DatagramSocket
C.UDPPacket
D.DatagramPacket
8.在使用UDP套接字通信時,常用(D)類把要發送的信息打包。(選擇一項)
A String
B.DatagramSocket
C.MulticastSocket
D.DatagramPacket
三、 判斷題
1. Socket是傳輸層供給應用層的編程介面,是應用層與傳輸層之間的橋梁 。( T )
2. TCP/IP傳輸控制協議是Internet的主要協議,定義了計算機和外設進行通信的規則。TCP/IP網路參考模型包括七個層次:應用層、會話層、表示層、傳輸層、網路層、鏈路層和物理層。( F )
3. TCP協議一種面向連接的、可靠的、基於位元組流的通信協議 。HTTP、FTP、TELNET、SMTP 都是基於TCP協議的應用層協議。( T )
4. UDP協議是一種面向無連接的、可靠的、基於位元組流的傳輸層通信協議,該協議佔用系統資源多、效率較低。( F )
四、 簡答題
1.TCP/IP協議棧中,TCP協議和UDP協議的聯系和區別?
2.簡述基於TCP的Socket編程的主要步驟。提示:分別說明伺服器端和客戶端的編程步驟。
3.簡述基於UDP的Socket編程的主要步驟。提示:分別說明伺服器端和客戶端的編程步驟。
五、 編碼題
1.使用基於TCP的Java Socket編程,完成如下功能:
1) 要求從客戶端錄入幾個字元,發送到伺服器端。
2) 由伺服器端將接收到的字元進行輸出。
3) 伺服器端向客戶端發出「您的信息已收到」作為響應。
4) 客戶端接收伺服器端的響應信息。
提示:
伺服器端:PrintWriter out =new PrintWriter(socket.getOutputStream(),true);
客戶端:BufferedReader line=new BufferedReader(new InputStreamReader(System.in));
B. 急求:網路問題:伯克利套接字是什麼
本文介紹 Windows Sockets 的性質和用途。其他內容還包括:
定義術語「套接字」。
描述 SOCKET 句柄數據類型。
描述套接字的用途。
Windows Sockets 規范為 Microsoft Windows 定義了一個二進制兼容網路編程介面。Windows Sockets 基於 Berkeley Software Distribution(BSD,4.3 版)中的 UNIX 套接字實現,後者是美國加州大學伯克利分校開發的。該規范包括針對 Windows 的 BSD 樣式套接字常式和擴展。通過使用 Windows Sockets,應用程序能夠在任何符合 Windows Sockets API 的網路上通信。在 Win32 上,Windows Sockets 提供線程安全。
許多網路軟體供應商支持網路協議下的 Windows Sockets,這些協議包括:傳輸控制協議/網際協議 (TCP/IP)、Xerox 網路系統 (XNS)、Digital Equipment Corporation 的 DECNet 協議和 Novell Corporation 的互聯網包交換協議/順序分組報文交換協議 (IPX/SPX) 等。雖然目前的 Windows Sockets 規范定義了 TCP/IP 的套接字抽象化,但任何網路協議都可以通過提供自己版本的、實現 Windows Sockets 的動態鏈接庫 (DLL) 來滿足 Windows Sockets。用 Windows Sockets 編寫的商用應用程序示例包括 X Windows 伺服器、終端模擬器和電子郵件系統。
注意: Windows Sockets 的用途是將基礎網路抽象出來,這樣,您不必對網路非常了解,並且您的應用程序可在任何支持套接字的網路上運行。因此,本文檔不討論網路協議的細節內容。
Microsoft 基礎類庫 (MFC) 通過提供兩個類來支持使用 Windows Sockets API 進行編程。其中一個類為 CSocket ,它提供高級抽象化來簡化網路通信編程。
Windows Sockets 規范「Windows Sockets:用於 Microsoft Windows 環境下的網路計算的開放介面」現在為 1.1 版本,它是 TCP/IP 群體中一個由個人和公司組成的大團體開發的,是一個開放的網路標准,可免費使用。套接字編程模型當前支持一個「通信域」,該「通信域」使用網際協議組 (Internet Protocol Suite)。該規范可在 Platform SDK 中獲得。
提示: 因為套接字使用網際協議組,所以它們對於支持「信息高速公路」上 Internet 通信的應用程序是首選方式。
套接字的定義
套接字是一個通信終結點,它是 Windows Sockets 應用程序用來在網路上發送或接收數據包的對象。套接字具有類型,與正在運行的進程相關聯,並且可以有名稱。目前,套接字一般只與使用網際協議組的同一「通信域」中的其他套接字交換數據。
這兩種套接字都是雙向的,是可以同時在兩個方向上(全雙工)進行通信的數據流。
可用的套接字類型有以下兩種:
流式套接字
流式套接字提供沒有記錄邊界的數據流,即位元組流。位元組流能確保以正確的順序無重復地被送達。
數據文報套接字
數據文報套接字支持面向記錄的數據流,但不能確保能被送達,也無法確保按照發送順序或不重復。
「有序」指數據包按發送的順序送達。「不重復」指一個特定的數據包只能獲取一次。
注意: 在某些網路協議下(如 XNS),流可以面向記錄,即作為記錄流而非位元組流。但在更常用的 TCP/IP 協議下,流為位元組流。Windows Sockets 提供與基礎協議無關的抽象化級別。
有關上述類型以及各種套接字適用情形的信息,請參見 Windows Sockets:流式套接字和 Windows Sockets:數據文報套接字。
SOCKET 數據類型
每一個 MFC 套接字對象封裝一個 Windows Sockets 對象的句柄。該句柄的數據類型為 SOCKET。SOCKET 句柄類似於窗口的 HWND。MFC 套接字類提供對封裝句柄的操作。
Platform SDK 中詳細描述了 SOCKET 數據類型。
套接字的用途
套接字的作用非常大,至少在下面三種通信上下文中如此:
客戶端/伺服器模型。
對等網路方案,如聊天應用程序。
通過讓接收應用程序將消息解釋為函數調用來進行遠程過程調用 (RPC)。
C. Java網路編程如何初始化套接字
不同的構造方法不僅帶的參數不同,所具有的意義也不一樣。下面分別解析這兩個類的實例初始化過程。 ServerSocket 實例的初始化 ServerSocket 類提供了四個構造器: public Socket(String host, int port) throws UnknownHostException, IOException public Socket(InetAddress address, int port) throws IOException public Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException public Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException public Socket() public Socket(Proxy proxy) 帶參構造器用來創建已綁定的伺服器套接字,也就是說構造成功後它就已經開始偵聽指定的埠,且能夠調用 accept() 方法來接受客戶端連接。默認構造器則會創建未綁定的伺服器套接字,構造成功後必須手動將其綁定到一個本地地址才能用,在綁定之前可以進行一些選項配置。 帶參構造器 總的來說,帶參構造器提供了三個參數: port 指定該伺服器套接字所要偵聽的本地埠。如果為 0,則由系統自動分配一個埠號,這必須以另外的方式讓客戶端獲取埠號。 backlog 這個名詞目前還沒有合適的譯名。底層系統的 TCP 實現會維護一個連接隊列,該隊列緩存了已被 TCP 處理完畢,但還沒有被伺服器套接字接受的客戶端連接。一旦某個連接被接受(通過調用 accept() 方法),它就會被從隊列中移除。backlog 參數就用於指定隊列的最大長度,默認值為 50,但這個值只是一個建議,底層系統可能根據需要自動調整。如果隊列滿了,則其行為是平台相關的:微軟的 WINSOCK 會拒絕新的連接,其他實現則什麼都不做。嚴格地說,微軟沒有遵守規范,破壞了游戲規則…… bindAddr 一台機器可能會有多個本地 IP 地址,例如同時使用多塊網卡。使用其他兩個帶參構造器時,該參數為 null,伺服器套接字會在所有的本地 IP 地址(0.0.0.0 或 ::0)上偵聽。如果希望只偵聽一個地址,則可使用該參數。 默認構造器 如果使用默認構造器,在綁定地址前,還可以做些配置。綁定操作由兩個 bind 方法定義,參數類似於帶參構造器。配置項包括以下方面(都必須在綁定前配置): 設置是否重用本地地址 該選項由 setReuseAddress(boolean on) 方法配置,對應底層系統的 SO_REUSEADDR 套接字選項。JDK 沒有定義該選項的默認值。如果該選項為 false,則在關閉 TCP 連接時,為了保證可靠性,該連接可能在關閉後的一段時間(大約兩分鍾)內保持超時狀態(通常稱為 TIME_WAIT 狀態或 2MSL 等待狀態),這段時間里無法將新建的伺服器套接字綁定到同一個地址。在開發階段,伺服器可能不斷重啟,打開改選項會非常有用。 設置接收緩沖區大小 該選項由 setReceiveBufferSize(int size) 方法配置,對應底層系統的 SO_RCVBUF 套接字選項,單位是位元組。《RFC 1323 - TCP Extensions for High Performance》將緩沖區大小定義為 64KB。該選項只是一個建議值,底層系統可能根據需要自行調整。 設置超時值 該選項由 setSoTimeout(int timeout) 方法配置,對應底層系統的 SO_TIMEOUT 套接字選項,單位是毫秒。默認值為 0。該選項影響 accept 方法的阻塞時間長度,如果超時將引發 SocketTimeoutException。如果設為 0,則表示永不超時。 設置性能首選項 性能首選項包括連接時間、延遲和帶寬三個選項,由 setPerformancePreferences(int connectionTime, int latency, int bandwidth) 方法配置。這三個數值分別表示短連接時間、低延遲和高帶寬的相對重要性,數值越大則越重要;其各自的絕對值沒有意義。該方法的初衷是為了讓 Java 能在用非 TCP/IP 實現的套接字環境下工作得更好,某些需要對網路進行調優的程序也可以將這三個首選項作為配置參數提供給用戶。 Socket 實例的初始化 Socket 類提供了六個公共構造器(已過時的除外): public Socket(String host, int port) throws UnknownHostException, IOException public Socket(InetAddress address, int port) throws IOException public Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException public Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException public Socket() public Socket(Proxy proxy) 前四個構造器創建已連接的客戶端套接字,也就是說構造的時候就會去連接伺服器。前兩個構造器需要提供伺服器的地址和埠作為參數,本地地址和埠由系統自動分配;後兩個允許手動指定本地地址和埠,但極少使用。後兩個構造器創建未連接的套接字,創建後需要調用 connect 方法手動連接,連接之前可以做一些配置。最後一個構造器接受一個代表代理服務其的 Proxy 對象,JDK 支持 HTTP 和 SOCKS(V4 或 V5)兩種代理類型。 連接前的配置 在連接前,客戶端套接字不僅像伺服器套接字那樣可以設置是否重用本地地址、緩沖區大小、超時值和性能首選項,還能夠配置以下各項(都必須在連接前配置): 設置是否保持活躍 該選項由 setKeepAlive(boolean on) 方法配置,對應底層系統的 SO_KEEPALIVE 套接字選項。默認值為 false。如果打開該選項,則套接字會定期自動發送保持活躍的探測性消息,類似於心跳檢測。根據《RFC 1122 - Requirements for Internet Hosts》的規定,保持活躍機制只是 TCP 的一個可選功能,如果支持的話,默認必須為 false,而且這種機制默認在成功建立連接後,且連續兩小時沒有數據傳輸的情況下才會被激活。從另一方面來看,通過套接字的 I/O 操作完全可以知道連接是否還有效,所以該選項的實用價值不大。 設置是否收發帶外數據 該選項由 setOOBInline(boolean on) 方法配置,對應底層系統的 SO_OOBINLINE 套接字選項。默認值為 off。帶外數據(Out-of-band Data)也叫做緊急數據,表示數據很重要,需要使用不同於發送普通數據的一個專用通道來發送。打開該選項後,就可以調用 sendUrgentData(int data) 方法發送一個位元組的緊急數據。JDK 對帶外數據只提供了有限支持,緊急數據將會和普通數據一起被收到,並且無法自動區分。該選項對應用開發人員意義不大。 設置是否從容關閉連接 該選項由 setSoLinger(boolean on, int linger) 方法配置,對應底層系統的 SO_LINGER 套接字選項。默認為 false。該選項只會影響套接字的關閉,其中的 linger 參數表示超時時間,單位為秒。如果打開改選項:如果將 linger 設為 0,則關閉套接字的時候,未發送的數據會被丟棄,且另一端會出現連接被同位體重置的異常;如果 linger 非 0,則關閉套接字的線程將被阻塞,直到數據全部發送或超時,超時後的行為與底層系統相關,JDK 無法控制。如果關閉該選項,則套接字正常關閉,數據也會全部發送。由於底層實現的差異性,不提倡應用開發人員打開該選項。 設置是否延遲發送數據 該選項由 setTcpNoDelay(boolean on) 方法配置,對應底層系統的 TCP_NODELAY TCP 選項。默認值為 off。打開該選項將禁用 Nagle 演算法,TCP 包會立即發送;關閉該選項則會啟用 Nagle 演算法,多個較小的 TCP 包會被組合成一個大包一起發送,雖然發送延遲了,但有利於避免網路擁塞。默認為 false。該選項對實時性很強的程序可能有用,但一般的程序不需要關心。 設置流量類別 該選項由 setTrafficClass(int tc) 方法配置,對應底層系統的「流量類別」套接字屬性。該選項用於向網路(例如路由器)提示從該套接字發送的包需要獲取哪些服務類型,對本地 TCP 協議棧沒有影響。IPv4 和 IPv6 分別定義了多個不同的值,例如 IPv4 將 0x08 定義為最大吞吐量,0x10 定義為最小延遲,等等。可以用或運算將多個值合並為一個選項。該選項用來調整性能,需要根據實際情況設置。由於只是建議值,可能被網路忽略。
D. 求一個關於JAVA的論文
目 錄
一、概要設計……………………………………………………………3
二、程序整體設計說明…………………………………………….…..4
三、程序部分源代碼及注釋…………………………………………….9
四、測試結果………………………………………………………….24
五、設計心得…………………………………………………………25
六、致 謝…………………………………………………………25
七、參考文獻…………………………………………………………25
【摘 要】該程序是一個圖形界面的java文檔編輯器,其界面主要採用了awt包, 程序實現了文本編輯器的基本功能有:新建文件、打開文件、文件保存、文件另存為、剪切、復制、粘貼、刪除、查找/替換、改變字體大小,另外還利用Time類的schele方法實現了文件的定時自動更新功能,並創建備份文件,由於該編輯器是用的awt包,所以在技術上沒有實現將Java的關鍵字以不同顏色顯示功能。
【關鍵字】java 編輯器
一、概要設計
Java程序編輯器是:圖形界面、線程、流與文件等技術的綜合應用。
圖形界面的實現:考慮到簡單、實用、高效等特點,就選擇了AWT來完成實現,在選擇組件上,文本編輯區就選用了TaxtArea作為主要的部件。
線程實現文件自動保存:在相關的參考書上查閱到在Time類中有一個schele方法可以在後台自動完成一定的功能,而且調用起來相當簡單,於是就用了Time類中的schele方法來實現文件自動保存及備份功能。
文件操作的實現:利用了字元文件流FileReader和FileWriter類來實現。
由於Java的特性,可能用任何一個編輯器來編輯,於是就將Windows中的記事本作為模仿對象,根據實現情況刪減了其中的一些功能,如自動換行,設置字體,列印等功能。
在設計類的時候,考慮到簡單明了,就用了兩個類,一個主類和一個默認屬性類作為程序的整體框架,所有的對象和方法都是在默認屬性類中創建和實現的,以及為各組件注冊事件監聽程序也是在默認屬性類中實現的。主類完成對象的實例化及顯示。這們設計的優點是:條理清晰,容易理解,容易修改。這樣設計的缺點是:不利於共享類中的方法。
二、程序整體設計說明
2.1、程序框架圖
2.2、程序中所用類說明
(1)用戶自定義類
類名:EditInstantiation
作用:實例化對象
繼承的父類:WindowAdapter
主要成員變數:
Frame myFrm // 定義主窗體
TextArea myText // 定義文本編輯區
Dialog myDlgFind,myDlgFindont //查找及設置字體對話框
TextField TFfind, TFreplace, TffontSize
//查找對話框和字體窗體中的文本行
Button BfontOK, Bfind, Breplace, Bnext, Bcancel //定義和創建各按鈕
Label Lf, Lr, Ls //定義和創建各標簽
MenuBar Mbbar //定義和創建主菜單
Menu Mfile,Medit,Mformation,Mhelp //定義和創建主菜單中的選項
Toolkit toolKit
Clipboard myCB //剪切板對象
FileDialog myFDlg //定義文件對話框
Choice ChfontName //定義和創建字體選擇框
private int VIindex = 1; //構成文件名後綴變數
private String VSsubFixStr=".java"; //構成文件名擴展名變數
private String VSmyFileName = "Document1",VSmyBFileName;
//文件名及備份文件名變數
private File VFmyFile=new File(VSmyFileName+VIindex+".java");
//文件名變數
private int VIsearchPosition=0; //查找位置指針
private Timer VTtime; //實例化一個Time類
private int VImin=1; // schele方法中的一個時間參數
private int VItype=JOptionPane.INFORMATION_MESSAGE;
//提示對話框類型
private String VStitle; //提示對話框標題
private String VSmessage; //提示對話框信息
private boolean VBchanged = true; //改變字體的一個標識
private int VIfontSizeMin = 8, VIfontSizeMax = 40, VIfontSizeChangedStep = 2; //設置字體大小及步長
主要成員方法:
public void init() //初始化各部件菜單的定義和事件的監聽
public void displayEdit ()//顯示窗體及調用Time中的schele方法
public void windowClosing () //關閉窗體
public void save //保存文件方法
a.內部類類名:KeyEvents
作用:實現菜單的事件的響應功能
繼承的父類:KeyAdapter
主要成員變數:無
成員方法:actionPerformed()、keyPressed()
b.內部類類名:FindKeyEvent
作用:實現查找中各部件事件的響應功能
繼承的父類:無
主要成員變數:無
成員方法:actionPerformed ()
c.內部類類名:fontEvent
作用:實現字體中各部件事件的響應功能
繼承的父類:無
主要成員變數:無
成員方法:ItemListener(),ActionListener()
(2)用戶自定義類與Java類的繼承關系圖如下:
自定義類 Java 類
線程使用說明
2.3、實現介面方法
本程序用到的方法有:schele其方法描述如下:
schele(事件,啟動時間,間隔時間);
2.4、線程應用
本程序為文本編輯器,為實現自動更新,應用到了線程,每隔1分鍾對文件進行自動更新
2.5、異常處理說明
(1)打開文件時的異常處理
需要處理的異常:IOException
處理方法:捕獲異常後,顯示捕獲的異常
(2)保存文件時的異常處理
需要處理的異常:IOException
處理方法:捕獲異常後,顯示捕獲的異常
2.6、程序運行效果及存在的問題
(1)程序運行主要界面如下:
a、主界面
b、打開文件對話框
c、保存文件對話框
d、另存為文件對話框
e、查找/替換對話框
f.字體對話框
2.7.程序尚還存在的問題
我花費了近一個多星期的時間,查閱了許多相關的資料,終於把這個Java編輯器,程序基本實現了該課程設計的基本要求。但由於自己水平有限,使得程序還有不是很完善,首先,最重要的一點是該設計的最重要的功能自動改變java關鍵字的顏色沒有實現。
三、程序部分源代碼及注釋
//****************************************************
// class name :Edit
// implements :none
// extends :none
// attribute :public
// founction :entrance of the class
//*****************************************************
public class Edit{ //主類
public static void main(String args[]){
EditInstantiation myEdit= new EditInstantiation();
myEdit.init(); //初始化
myEdit.displayEdit(); //顯示窗體
}
//****************************************************
// class name :EditInstantiation
// implements :none
// extends :WindowAdapter
// attribute :default
// founction :EditInstantiation of the main class
//*****************************************************
class EditInstantiation extends WindowAdapter{ //默認屬性類
//define sources 定義各部件
Frame myFrm=new Frame("我的編輯器"); //定義窗體
TextArea myText=new TextArea(); //定義窗體
Dialog myDlgFind=new Dialog(myFrm,"查找",true); //定義查找對話框
Dialog myDlgFindont=new Dialog(myFrm,"字體",true); //定義字體對話框
TextField TFfind=new TextField(30);//定義查找對話中的查找輸入框
TextField TFreplace=new TextField(30); //定義查找對話中的替換輸入框
TextField TFfontSize,TFfontDemo;//定義字體大小文本框和示例框
Choice CHfontName;//定義字體大小選擇框
List LTfontSize; //定義字體大小標簽
Button BfontOK,BfontCancel; //定義字體大小對話中的確定及取消按鈕
Button Bfind=new Button("查找");//定義查找對話中的查找按鈕
Button Breplace=new Button("替換");//定義查找對話中的替換及取消按鈕
Button Bnext=new Button("下一個");//定義查找對話中的下一個及取消按鈕
Button Bcancel=new Button("取消");//定義查找對話中的確定及取消按鈕
Label Lf=new Label("查找內容:");
Label Lr=new Label("替換為: ");
Label Ls=new Label("字體大小:");
FileDialog myFDlg;
Clipboard myCB=Toolkit.getDefaultToolkit().getSystemClipboard(); //剪切板對象
Menu Mfile,Medit,Mformation,Mhelp;
MenuBar MBbar;
//define varities //定義各變數
private int VIindex = 1;
private String VSsubFixStr=".java";
private String VSmyFileName = "Document1",VSmyBFileName;
private File VFmyFile=new File(VSmyFileName+VIindex+".java");
private int VIsearchPosition=0;
private Timer VTtime;
private int VImin=1; // parameter in time schel
private int VItype=JOptionPane.INFORMATION_MESSAGE;
private String VStitle;
private String VSmessage;
// flag of the changeing
private boolean VBchanged = true;
// the scope of the font
private int VIfontSizeMin = 8, VIfontSizeMax = 40, VIfontSizeChangedStep = 2;
//************************************************
//founction name:init()
//parameter :none
//attribute :public
//founction :initia all compont
//************************************************
public void init(){ //初始化各部件
//------------------ set menu ------------------
MBbar=new MenuBar();
myFrm.setMenuBar(MBbar);
Mfile=new Menu("文件");
Medit=new Menu("編輯");
Mformation=new Menu("格式");
Mhelp=new Menu("幫助");
MBbar.add(Mfile);
MBbar.add(Medit);
MBbar.add(Mformation);
MBbar.add(Mhelp);
//文件菜單 add File menu
Mfile.add(new MenuItem("新建",new MenuShortcut(KeyEvent.VK_N)));
Mfile.add(new MenuItem("打開",new MenuShortcut(KeyEvent.VK_O)));
Mfile.add(new MenuItem("保存",new MenuShortcut(KeyEvent.VK_S)));
Mfile.add(new MenuItem("另存為"));
Mfile.addSeparator();//分隔線
Mfile.add(new MenuItem("退出",new MenuShortcut(KeyEvent.VK_E)));
//編輯菜單 add Edit menu
Medit.add(new MenuItem("剪切"));//,new MenuShortcut(KeyEvent.VK_X)));
Medit.add(new MenuItem("復制"));//new MenuShortcut(KeyEvent.VK_C)));
Medit.add(new MenuItem("粘貼"));//new MenuShortcut(KeyEvent.VK_V)));
Medit.add(new MenuItem("刪除"));//new MenuShortcut(KeyEvent.VK_D)));
Medit.addSeparator();//分隔線
Medit.add(new MenuItem("查找/替換",new MenuShortcut(KeyEvent.VK_F)));
Medit.addSeparator();//分隔線
Medit.add(new MenuItem("全選",new MenuShortcut(KeyEvent.VK_A)));
//格式菜單 add Formation menu
Mformation.add(new MenuItem("字體",new MenuShortcut(KeyEvent.VK_U)));
//幫助菜單 add Formation menu
Mhelp.add(new MenuItem("關於作者"));
//----------------- menu add end -------------------------
//add Menu Action Listener
Mfile.addActionListener(new KeyEvents());
Medit.addActionListener(new KeyEvents());
Mformation.addActionListener(new KeyEvents());
Mhelp.addActionListener(new FindKeyEvent());
//--------------------------- Find dialog-----------------
myDlgFind.setSize(350,115);
myDlgFind.setLocation(250,150);
myDlgFind.setLayout(new FlowLayout(FlowLayout.CENTER));
myDlgFind.setBackground(Color.LIGHT_GRAY);
Bfind.setEnabled(false);
Breplace.setEnabled(false);
Bnext.setEnabled(false);
myDlgFind.add(Lf);
myDlgFind.add(TFfind);
myDlgFind.add(Lr);
myDlgFind.add(TFreplace);
myDlgFind.add(Bfind);
myDlgFind.add(Breplace);
myDlgFind.add(Bnext);
myDlgFind.add(Bcancel);
myDlgFind.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
myDlgFind.setVisible(false);
}});//為查找對話框窗體注冊事件監聽
TFfind.addKeyListener(new KeyEvents());//注冊事件監聽
Bfind.addActionListener(new FindKeyEvent());
Breplace.addActionListener(new FindKeyEvent());
Bcancel.addActionListener(new FindKeyEvent());
Bnext.addActionListener(new FindKeyEvent());
//--------------- end add action listener ------------
//================set font dialog ==============
//font size text field
TFfontSize = new TextField("8",14);
TFfontSize.selectAll();
//font size list field
LTfontSize = new java.awt.List(5, false);
LTfontSize.addItemListener(new fontEvent());
for(int i = VIfontSizeMin; i <= VIfontSizeMax; i = i + VIfontSizeChangedStep)
LTfontSize.add(i + "");//添加字體大小
LTfontSize.select(0);
//two Button Ok Cancel
BfontOK = new Button("確定");
BfontOK.addActionListener(new fontEvent());
BfontCancel = new Button("取消");
BfontCancel.addActionListener(new fontEvent());
//a TextField for demo the font
TFfontDemo = new TextField("Java awt",37);
TFfontDemo.setEditable(false);
// my font dialog設置字體對話框
myDlgFindont.setLayout(new FlowLayout(FlowLayout.LEFT));
myDlgFindont.setBackground(Color.LIGHT_GRAY);
myDlgFindont.add(Ls);
myDlgFindont.add(TFfontSize);
myDlgFindont.add(BfontOK);
myDlgFindont.add(BfontCancel);
myDlgFindont.add(LTfontSize);
myDlgFindont.add(TFfontDemo);
myDlgFindont.setSize(300,200);
myDlgFindont.setLocation(300,200);
myDlgFindont.setResizable(false);
myDlgFindont.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
myDlgFindont.show(false);
}
}); //為字體對話框窗體注冊事件監聽
//=============end set font dialog
// =======set Edit frame設置編輯器窗休
myFrm.add(myText,BorderLayout.CENTER);
myFrm.setSize(500,400);
myFrm.setBackground(Color.lightGray);
myFrm.addWindowListener(this);
myFrm.setSize(500,400);
myFrm.setLocation(200,100);
myFrm.setTitle("Java編輯器");
}
//************************************************
//founction name:displayEdit()
//parameter :none
//attribute :public
//founction :initial and display the frame
//************************************************
public void displayEdit(){ //顯示窗體
myFrm.setVisible(true);
//---------------------- auto save ---------------------
VTtime = new Timer(true);
VTtime.schele(new java.util.TimerTask(){
public void run(){
if(VSmyFileName!=null){
save(VSmyFileName+".java");
VSmyBFileName=VSmyFileName+".bak";
} //添加自動保存功能
save(VSmyBFileName);
}
}, VImin*60*1000,VImin*60*1000);
//parament 1 the task
//parament 2 when to start the task
//parament 3 set the interval time }
//****************************************************
// class name :KeyEvents
// implements :ActionListener
// extends :KeyAdapter
// attribute :default
// founction :implement the mouse and key action
//*****************************************************
class KeyEvents extends KeyAdapter implements ActionListener{
//********************************************************
//founction name:actionPerformed()
//parameter :none
//attribute :public
//return :void
//founction :realize the key action in the menu
//*********************************************************
public void actionPerformed(ActionEvent e){
//完成菜單事件的功能
// File Menu
if (e.getActionCommand()=="新建"){
//remind you
JFrame aFrame=new JFrame();
aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JOptionPane optionPane=new JOptionPane();
String choices[]={"是","否","取消"};
int n=optionPane.showOptionDialog(aFrame,"文件正文已更改,是否保存更改","文本編輯器",JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.WARNING_MESSAGE,null,choices,choices[0]);
//保存文件後新建
if(n==0){//若文件存在,保存在原文件中,再新建文件
try{
if(VFmyFile.exists()){
save(VSmyFileName); // call the save founction
myText.setText("");
VIindex++;
}
else{//若文件不存在,則保存後再新建
myFDlg=new FileDialog(myFrm,"保存文件",FileDialog.SAVE);
myFDlg.setFile(VSmyFileName);
myFDlg.show();
VSmyFileName=myFDlg.getDirectory()+myFDlg.getFile();
save(VSmyFileName);
myText.setText("");
VIindex++;
}
}
catch(Exception ne){}
}
//不保存文件新建
if(n==1){
myText.setText("");
VIindex++;
}
//取消新建
if(n==0){return;}
}
//打開菜單 Open Menu
if (e.getActionCommand()=="打開") {
myFDlg=new FileDialog(myFrm,"打開",FileDialog.LOAD);
myFDlg.show();
if (myFDlg.getFile()!="") {
VFmyFile=new File(myFDlg.getDirectory()+myFDlg.getFile());
VSmyFileName=myFDlg.getDirectory()+myFDlg.getFile();
if( VFmyFile.exists()){
try{
FileReader fr=new FileReader(VFmyFile);
BufferedReader br=new BufferedReader(fr);
String text;
myText.setText("");
while ((text=br.readLine())!=null)
myText.append(text+"\r\n");
br.close();
fr.close();
}
catch(IOException ioe){
VStitle="提示";
VSmessage="打開文件出錯";
JOptionPane.showMessageDialog(myFrm,VSmessage,VStitle,VItype);
}
}
}
}
//保存菜單 Save Menu
if (e.getActionCommand()=="保存"){
myFDlg=new FileDialog(myFrm,"保存文件",FileDialog.SAVE);
myFDlg.setFile(VSmyFileName);
myFDlg.show();
VSmyFileName=myFDlg.getFile();
if(VSmyFileName!=null){
VSmyFileName=myFDlg.getDirectory()+myFDlg.getFile();
save(VSmyFileName);
}
}
//另存為菜單 SaveAs Menu
if (e.getActionCommand()=="另存為"){
myFDlg=new FileDialog(myFrm,"文件另存為",1);
myFDlg.setFile(VSmyFileName);
myFDlg.show();
VSmyFileName=myFDlg.getFile();
if(VSmyFileName!=null){
VSmyFileName=myFDlg.getDirectory()+myFDlg.getFile();
save(VSmyFileName);
}
}
//退出菜單 exit Menu
if (e.getActionCommand()=="退出")
System.exit(0);
//編輯 Edit Menu
if (e.getActionCommand()=="剪切"){
//Cut
String text =myText.getSelectedText();
StringSelection selection = new StringSelection(text);
myCB.setContents(selection, null);
myText.replaceRange("",myText.getSelectionStart(),myText.getSelectionEnd());
}
if (e.getActionCommand()=="復制"){
//
String text=myText.getSelectedText();
if(text!=null){
StringSelection selection=new StringSelect
E. 在javasocket網路編程中,開發基於udp協議的程序使用的套接字有哪些
Socket套接字,是由系統提供用於網路通信的技術(操作系統給應用程序提供的一組API叫做Socket API),是基於TCP/IP協議的網路通信的基本操作單元。基於Socket套接字的網路程序開發就是網路編程。
socket可以視為是應用層和傳輸層之間的通信橋梁;
傳輸層的核心協議有兩種:TCP,UDP;socket API也有對應的兩組,由於TCP和UDP協議差別很大,因此,這兩組API差別也挺大。
分類:
Socket套接字主要針對傳輸層協議劃分為如下三類:
流套接字:使用傳輸層TCP協議
TCP,即Transmission Control Protocol(傳輸控制協議),傳輸層協議;
TCP的特點:
有連接:像打電話,得先接通,才能交互數據;
可靠傳輸:傳輸過程中,發送方知道接收方有沒有收到數據.(打電話就是可靠傳輸);
面向位元組流:以位元組為單位進行傳輸.(非常類似於文件操作中的位元組流);
全雙工:一條鏈路,雙向通信;
有接收緩沖區,也有發送緩沖區。
大小不限
對於位元組流來說,可以簡單的理解為,傳輸數據是基於IO流,流式數據的特徵就是在IO流沒有關閉的情況下,是無邊界的數據,可以多次發送,也可以分開多次接收。
數據報套接字:使用傳輸層UDP協議
UDP,即User Datagram Protocol(用戶數據報協議),傳輸層協議。
UDP的特點:
無連接:像發微信,不需要接通,直接就能發數據;
不可靠傳輸:傳輸過程中,發送方不知道接收方有沒有收到數據.(發微信就是不可靠傳輸);
面向數據報:以數據報為單位進行傳輸(一個數據報都會明確大小)一次發送/接收必須是一個完整的數據報,不能是半個,也不能是一個半;
全雙工:一條鏈路,雙向通信;
有接收緩沖區,無發送緩沖區;
大小受限:一次最多傳輸64k;
對於數據報來說,可以簡單的理解為,傳輸數據是一塊一塊的,發送一塊數據假如100個位元組,必須一次發送,接收也必須一次接收100個位元組,而不能分100次,每次接收1個位元組。
原始套接字
原始套接字用於自定義傳輸層協議,用於讀寫內核沒有處理的IP協議數據。
二、UDP數據報套接字編程
UDPSocket中,主要涉及到兩類:DatagramSocket、DatagramPacket;
DatagramSocket API
DatagramSocket 創建了一個UDP版本的Socket對象,用於發送和接收UDP數據報,代表著操作系統中的一個socket文件,(操作系統實現的功能–>)代表著網卡硬體設備的抽象體現。
DatagramSocket 構造方法:
方法簽名 方法說明
DatagramSocket() 創建一個UDP數據報套接字的Socket,綁定到本機任意一個隨機埠(一般用於客戶端)
DatagramSocket(int port) 創建一個UDP數據報套接字的Socket,綁定到本機指定的埠(一般用於服務端)
DatagramSocket 方法:
方法簽名 方法說明
void receive(DatagramPacket p) 從此套接字接收數據報(如果沒有接收到數據報,該方法會阻塞等待)
void send(DatagramPacket p) 從此套接字發送數據報包(不會阻塞等待,直接發送)
void close() 關閉此數據報套接字
DatagramPacket API
代表了一個UDP數據報,是UDP Socket發送和接收的數據報,每次發送/接收數據報,都是在傳輸一個DatagramPacket對象。
DatagramPacket 構造方法:
方法簽名 方法說明
DatagramPacket(byte[] buf, int length) 構造一個DatagramPacket以用來接收數據報,接收的數據保存在位元組數組(第一個參數buf)中,接收指定長度(第二個參數length)
DatagramPacket(byte[] buf, int offset, int length,SocketAddress address) 構造一個DatagramPacket以用來發送數據報,發送的數據為位元組數組(第一個參數buf)中,從0到指定長度(第二個參數length)。address指定目的主機的IP和埠號
DatagramPacket 方法:
方法簽名 方法說明
InetAddress getAddress() 從接收的數據報中,獲取發送端主機IP地址;或從發送的數據報中,獲取接收端主機IP地址
int getPort() 從接收的數據報中,獲取發送端主機的埠號;或從發送的數據報中,獲取接收端主機埠號
byte[] getData() 獲取數據報中的數據
構造UDP發送的數據報時,需要傳入 SocketAddress ,該對象可以使用 InetSocketAddress 來創建。
InetSocketAddress API
InetSocketAddress ( SocketAddress 的子類 )構造方法:
方法簽名 方法說明
InetSocketAddress(InetAddress addr, int port) 創建一個Socket地址,包含IP地址和埠號
示例1:寫一個簡單的客戶端服務程序,回顯服務(EchoSever)
在這里插入圖片描述
構建Socket對象有很多失敗的可能:
埠號已經被佔用,同一個主機的兩個程序不能有相同的埠號(這就好比兩個人不能擁有相同的電話號碼);
此處,多個進程不能綁定同一個埠號,但是一個進程可以綁定多個埠,(這就好比一個人可以擁有多個手機號),一個進程可以創建多個Socket對象,每個Socket都綁定自己的埠。
每個進程能夠打開的文件個數是有上限的,如果進程之間已經打開了很多文件,就可能導致此時的Socket文件不能順利打開;
在這里插入圖片描述
這個長度不一定是1024,假設這里的UDP數據最長是1024,實際的數據可能不夠1024.
在這里插入圖片描述
這里的參數不再是一個空的位元組數組了,response是剛才根據請求計算的得到的響應,是非空的,DatagramPacket 裡面的數據就是String response的數據。
response.getBytes().length:這里拿到的是位元組數組的長度(位元組的個數),而response.length得到的是字元的長度。
五元組
一次通信是由5個核心信息描述的:源IP、 源埠、 目的IP、 目的埠、 協議類型。
站在客戶端角度:
源IP:本機IP;
源埠:系統分配的埠;
目的IP:伺服器的IP;
目的埠:伺服器的埠;
協議類型:TCP;
站在伺服器的角度:
源IP:伺服器程序本機的IP;
源埠:伺服器綁定的埠(此處手動指定了9090);
目的IP:包含在收到的數據報中(客戶端的IP);
目的埠:包含在收到的數據報中(客戶端的埠);
協議類型:UDP;
F. java socket有什麼作用
所謂socket通常也稱作"套接字",用於描述IP地址和埠,是一個通信鏈的句柄。應用程序通常通過"套接字"向網路發出請求或者應答網路請求。
以J2SDK-1.3為例,Socket和ServerSocket類庫位於java.net包中。ServerSocket用於伺服器端,Socket是建立網路連接時使用的。在連接成功時,應用程序兩端都會產生一個Socket實例,操作這個實例,完成所需的會話。對於一個網路連接來說,套接字是平等的,並沒有差別,不因為在伺服器端或在客戶端而產生不同級別。不管是Socket還是ServerSocket它們的工作都是通過SocketImpl類及其子類完成的。
重要的Socket API:
java.net.Socket繼承於java.lang.Object,有八個構造器,其方法並不多,下面介紹使用最頻繁的三個方法,其它方法大家可以見JDK-1.3文檔。
. Accept方法用於產生"阻塞",直到接受到一個連接,並且返回一個客戶端的Socket對象實例。"阻塞"是一個術語,它使程序運行暫時"停留"在這個地方,直到一個會話產生,然後程序繼續;通常"阻塞"是由循環產生的。
. getInputStream方法獲得網路連接輸入,同時返回一個InputStream對象實例,。
. getOutputStream方法連接的另一端將得到輸入,同時返回一個OutputStream對象實例。
注意:其中getInputStream和getOutputStream方法均會產生一個IOException,它必須被捕獲,因為它們返回的流對象,通常都會被另一個流對象使用。
編輯本段ServerSocket類例子
int PORT = 8888; // 偵聽埠
// 創建ServerSocket
ServerSocket serverSocket = new ServerSocket(PORT);
// 開始循環
while (true) {
// 等待連接
Socket socket = serverSocket.accept();
// 處理鏈接的線程類
ServerThread st = new ServerThread(socket);
// 啟動線程處理
new Thread(st).start();
}
編輯本段客戶端的例子
int PORT = 8888; // 偵聽埠
// 建立連接
socket = new Socket(「127.0.0.1」, 8888);
// 輸入數據的讀取
BufferedReader netIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 寫入數據
PrintWriter netOut = new PrintWriter(socket.getOutputStream());
G. JAVA Socket 底層是怎樣基於TCP/IP 實現的
首先必須明確:TCP/IP模型中有四層結構: 應用層(Application Layer)、傳輸層(Transport Layer)、網路層(Internet Layer
)、鏈路層(LinkLayer)
其中Ip協議(Internet Protocol)是位於網路層的,TCP協議時位於傳輸層的。通過Ip協議可以使可以使兩台計算機使用同一種語言,從而允許Internet上連接不同類型的計算機和不同操作系統的網路。Ip協議只保證計算機能夠接收和發送分組數據。當計算機要和遠程的計算機建立連接時,TCP協議會讓他們建立連接:用於發送和接收數據的虛擬電路。
套接字或插座(socket)是一種軟體形式的抽象,用於表達兩台機器間一個連接的「終端」。針對一個特定的連接,每台機器上都有一個「套接字」,可以想像它們之間有一條虛擬的「線纜」。JAVA
有兩個基於數據流的套接字類:ServerSocket,伺服器用它「偵聽」進入的連接;Socket,客戶端用它初始一次連接。偵聽套接字只能接收新的連接請求,不能接收實際的數據包,即ServerSocket不能接收實際的數據包。
套接字是基於TCP/IP實現的,它是用來提供一個訪問TCP的服務介面,或者說套接字socket是TCP的應用編程介面API,通過它應用層就可以訪問TCP提供的服務。
在JAVA中,我們用 ServerSocket、Socket類創建一個套接字連接,從套接字得到的結果是一個InputStream以及OutputStream對象,以便將連接作為一個IO流對象對待。通過IO流可以從流中讀取數據或者寫數據到流中,讀寫IO流會有異常IOException產生。
H. Java多線程編程,怎樣實現線程間數據的傳遞
可以用Scoket套接字讓伺服器和客戶端建立連接
可以根據Scoket對象的getInputStream()和getOutputStream()獲得輸入輸出流
再往流裡面寫信息
就實現了簡單的數據傳遞
當然等待數據
的時候會有阻塞現象
所以使用線程來保證數據不會因為等待而阻塞
I. 資料庫訪問中的套接字技術:運行下面代碼總是出現java.lang.NullPointerException
package,包,就像文件夾一樣,用來將不同的東西分類儲存的
java.applet包是用來實現運行於Internet瀏覽器中的Java Applet的工具類庫,它僅包含少量幾個介面和一個非常有用的類Java.applet.Applet。
java.awt包是Java語言用來構建圖形用戶界面(GUl)的類庫,它包括了許多界面元素和資源。利用java.awt包,開發人員可以很方便地編寫出美觀、方便、標准化的應用程序界面。java.awt包主要在三個方面提供界面設計支持:①低級繪圖操作,如Graphics類等;②圖形界面組件和布局管理,如Checkbox類、Container類、LayoutManager介面等;③界面用戶交互控制和事件響應,如Event類。
java.io包中包含了實現Java程序與操作系統、用戶界面以及其他Java程序之間進行數據交換所使用的類,如基本輸入/輸出流、文件輸入/輸出流、過濾輸入/輸出流、管道輸入/輸出流、隨機輸入/輸出流等。凡是需要完成與操作系統有關的較底層的輸入輸出操作的Java程序,都要用到java.io包。
java.lang:java.1ang包是Java語言的核心類庫,包含了運行Java程序必不可少的系統類,如基本數據類型、基本數學函數、字元串處理、線程、異常處理類等。每個Java程序運行時,系統都會自動地引入java.1ang包,所以這個包的載入是預設的。
java.net包是Java語言用來實現網路功能的類庫。由於Java語言還在不停地發展和擴充,它的功能,尤其是網路功能,也在不斷地擴充。目前已經實現的Java網路功能主要有:底層的網路通信,如實現套接字通信的Socket類、ServerSocket類;編寫用戶自己的Telnet、FTP、郵件服務等實現網上通信的類;用於訪問Internet上資源和進行CGl網關調用的類,如URL等。利用java.net包中的類,開發者可以編寫自己的具有網路功能的程序。
java.rmi包、java.rmi.registry包和java.rmi.server包
這三個包用來實現RMI(Remote Method Invocation,遠程方法調用)功能。利用RMI功能,用戶程序可以在遠程計算機(伺服器)上創建對象,並在本地計算機(客戶機)上使用這個對象。
java.security包、java.security.acl包和java.security.interfaces包
這三個包提供了更完善的Java程序安全性控制和管理,利用它們可以對Java程序加密,也可以把特定的Java Applet標記為「可信賴的」,使它能夠具有與Java Application相近的安全許可權。
java.sql包是實現JDBC(Java Database Connection)的類庫。利用這個包可以使Java程序具有訪問不同種類的資料庫(如Oracle,Sybase,DB2,SQLServer等)的功能。只要安裝了合適的驅動程序,同一個Java程序不需修改就可以存取、修改這些不同的資料庫中的數據。JDBC的這種功能,再加上Java程序本身具有的平台無關性,大大拓寬了Java程序的應用范圍,尤其是商業應用的適用領域。
java.util包中包括了Java語言中的一些低級的實用工具,如處理時間的Date類,處理變長數組的Vector類,實現棧的Stack類和實現哈希(散列)表的HashTable類等,使用它們開發者可以更方便快捷地編程。
J. Java中socket填的ip
首先必須明確:TCP/IP模型中有四層結構:
應用層(Application Layer)、傳輸層(Transport Layer)、網路層(Internet Layer )、鏈路層(LinkLayer)
其中Ip協議(Internet Protocol)是位於網路層的,TCP協議時位於傳輸層的。通過Ip協議可以使可以使兩台計算機使用同一種語言,從而允許Internet上連接不同類型的計算機和不同操作系統的網路。Ip協議只保證計算機能夠接收和發送分組數據。 當計算機要和遠程的計算機建立連接時,TCP協議會讓他們建立連接:用於發送和接收數據的虛擬電路。
在JAVA中,我們用 ServerSocket、Socket類創建一個套接字連接,從套接字得到的結果是一個InputStream以及OutputStream對象,以便將連接作為一個IO流對象對待。通過IO流可以從流中讀取數據或者寫數據到流中,讀寫IO流會有異常IOException產生。
套接字或插座(socket)是一種軟體形 式的抽象,用於表達兩台機器間一個連接的「終端」。針對一個特定的連接,每台機器上都有一個「套接字」,可以想像它們之間有一條虛擬的「線纜」。JAVA 有兩個基於數據流的套接字類:ServerSocket,伺服器用它「偵聽」進入的連接;Socket,客戶端用它初始一次連接。偵聽套接字只能接收新的 連接請求,不能接收實際的數據包,即ServerSocket不能接收實際的數據包。
套接字是基於TCP/IP實現的,它是用來提供一個訪問TCP的服務介面,或者說套接字socket是TCP的應用編程介面API,通過它應用層就可以訪問TCP提供的服務。
在JAVA中,我們用 ServerSocket、Socket類創建一個套接字連接,從套接字得到的結果是一個InputStream以及OutputStream對象,以便 將連接作為一個IO流對象對待。通過IO流可以從流中讀取數據或者寫數據到流中,讀寫IO流會有異常IOException產生。
套接字底層是基於TCP的,所以socket的超時和TCP超時是相同的。下面先討論套接字讀寫緩沖區,接著討論連接建立超時、讀寫超時以及JAVA套接字編程的嵌套異常捕獲和一個超時例子程序的抓包示例。
1 socket讀寫緩沖區
一旦創建了一個套接字實例,操作系統就會為其分配緩沖區以存放接收和要發送的數據。
JAVA可以設置讀寫緩沖區的大小-setReceiveBufferSize(int size), setSendBufferSize(int size)。
向輸出流寫數據並不意味著數據實際上已經被發送,它們只是被復制到了發送緩沖區隊列SendQ,就是在Socket的OutputStream上調用 flush()方法,也不能保證數據能夠立即發送到網路。真正的數據發送是由操作系統的TCP協議棧模塊從緩沖區中取數據發送到網路來完成的。
當有數據從網路來到時,TCP協議棧模塊接收數據並放入接收緩沖區隊列RecvQ,輸入流InputStream通過read方法從RecvQ中取出數據。
2 socket連接建立超時
socket連接建立是基於TCP的連接建立過程。TCP的連接需要通過3次握手報文來完成,開始建立TCP連接時需要發送同步SYN報文,然後等待確認 報文SYN+ACK,最後再發送確認報文ACK。TCP連接的關閉通過4次揮手來完成,主動關閉TCP連接的一方發送FIN報文,等待對方的確認報文;被 動關閉的一方也發送FIN報文,然等待確認報文。
正在等待TCP連接請求的一端有一個固定長度的連接隊列,該隊列中的連接已經被TCP接受(即三次握手已經完成),但還沒有被應用層所接受。TCP接受一個連接是將其放入這個連接隊列,而應用層接受連接是將其從該隊列中移出。應用層可以通過設置backlog變數來指明該連接隊列的最大長度,即已被TCP接受而等待應用層接受的最大連接數。
當一個連接請求SYN到達時,TCP確定是否接受這個連接。如果隊列中還有空間,TCP模塊將對SYN進行確認並完成連接的建立。但應用層只有在三次握手中的第三個報文收到後才會知道這個新連接。如果隊列沒有空間,TCP將不理會收到的SYN。
如果應用層不能及時接受已被TCP接受的連接,這些連接可能占滿整個連接隊列,新的連接請求可能不被響應而會超時。如果一個連接請求SYN發送後,一段時間後沒有收到確認SYN+ACK,TCP會重傳這個連接請求SYN兩次,每次重傳的時間間隔加倍,在規定的時間內仍沒有收到SYN+ACK,TCP將放棄這個連接請求,連接建立就超時了。
JAVA Socket連接建立超時和TCP是相同的,如果TCP建立連接時三次握手超時,那麼導致Socket連接建立也就超時了。可以設置Socket連接建立的超時時間-
connect(SocketAddress endpoint, int timeout)
如果在timeout內,連接沒有建立成功,在TimeoutException異常被拋出。如果timeout的值小於三次握手的時間,那麼Socket連接永遠也不會建立。
不同的應用層有不同的連接建立過程,Socket的連接建立和TCP一樣-僅僅需要三次握手就完成連接,但有些應用程序需要交互很多信息後才能成功建立連接,比如Telnet協議,在TCP三次握手完成後,需要進行選項協商之後,Telnet連接才建立完成。
3 socket讀超時
如果輸入緩沖隊列RecvQ中沒有數據,read操作會一直阻塞而掛起線程,直到有新的數據到來或者有異常產生。調用setSoTimeout(int timeout)可以設置超時時間,如果到了超時時間仍沒有數據,read會拋出一個SocketTimeoutException,程序需要捕獲這個異 常,但是當前的socket連接仍然是有效的。
如果對方進程崩潰、對方機器突然重啟、網路斷開,本端的read會一直阻塞下去(由前面可知:雙方要關閉連接需要四次揮手 .對方機重啟或斷開只是對方機的TCP連接關閉,本端的TCP連接還沒關閉,所以本端機會一直阻塞),這時設置超時時間是非常重要的,否則調用read的線程會一直掛起。
TCP模塊把接收到的數據放入RecvQ中,直到應用層調用輸入流的read方法來讀取。如果RecvQ隊列被填滿了,這時TCP會根據滑動窗口機制通知 對方不要繼續發送數據,本端停止接收從對端發送來的數據,直到接收者應用程序調用輸入流的read方法後騰出了空間。
4 socket寫超時
socket的寫超時是基於TCP的超時重傳。超時重傳是TCP保證數據可靠性傳輸的一個重要機制,其原理是在發送一個數據報文後就開啟一個計時器,在一 定時間內如果沒有得到發送報文的確認ACK,那麼就重新發送報文。如果重新發送多次之後,仍沒有確認報文,就發送一個復位報文RST,然後關閉TCP連 接。首次數據報文發送與復位報文傳輸之間的時間差大約為9分鍾,也就是說如果9分鍾內沒有得到確認報文,就關閉連接。但是這個值是根據不同的TCP協議棧 實現而不同。
如果發送端調用write持續地寫出數據,直到SendQ隊列被填滿。如果在SendQ隊列已滿時調用write方法,則write將被阻塞,直到 SendQ有新的空閑空間為止,也就是說直到一些位元組傳輸到了接收者套接字的RecvQ中。如果此時RecvQ隊列也已經被填滿,所有操作都將停止,直到 接收端調用read方法將一些位元組傳輸到應用程序。
當Socket的write發送數據時,如果網線斷開、對端進程崩潰或者對端機器重啟動,(由前面可知:雙方要關閉連接需要四次揮手 .對端進程崩潰或者對端機器重啟動只是對方機的TCP連接關閉,本端的TCP連接還沒關閉,所以本端機會一直阻塞)TCP模塊會重傳數據,最後超時而關閉連接。下次如再調用write會導致一個異常而退出。
Socket寫超時是基於TCP協議棧的超時重傳機制,一般不需要設置write的超時時間,也沒有提供這種方法。
5 雙重嵌套異常捕獲
如果ServerSocket、Socket構造失敗,只需要僅僅捕獲這個構造失敗異常而不需要調用套接字的close方法來釋放資源(必須保證構造失敗 後不會留下任何需要清除的資源),因為這時套接字內部資源沒有被成功分配。如果構造成功,必須進入一個try finally語句塊里調用close釋放套接字。請參照下面例子程序。
import java.net.*;
import java.io.*;
public class SocketClientTest
{
public static final int PORT = 8088;
public static void main( String[] args ) throws Exception
{
InetAddress addr = InetAddress.getByName( "127.0.0.1" );
Socket socket = new Socket();
try
{
socket.connect( new InetSocketAddress( addr, PORT ), 30000 );
socket.setSendBufferSize(100);
BufferedWriter out = new BufferedWriter( new OutputStreamWriter( socket.getOutputStream() ) );
int i = 0;
while( true )
{
System.out.println( "client sent --- hello *** " + i++ );
out.write( "client sent --- hello *** " + i );
out.flush();
Thread.sleep( 1000 );
}
}
finally
{
socket.close();
}
}
}
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServerTest
{
public static final int PORT = 8088;
public static final int BACKLOG = 2;
public static void main( String[] args ) throws IOException
{
ServerSocket server = new ServerSocket( PORT, BACKLOG );
System.out.println("started: " + server);
try
{
Socket socket = server.accept();
try
{
BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );
String info = null;
while( ( info = in.readLine() ) != null )
{
System.out.println( info );
}
}
finally
{
socket.close();
}
}
finally
{
server.close();
}
}
}