基於SMB協議的共享文件讀寫 博客分類: Java


一、SMB協議
SMB協議是基於TCP-NETBIOS下的,一般端口使用為139,445。
服務器信息塊(SMB)協議是一種IBM協議,用於在計算機間共享文件、打印機、串口等。SMB 協議可以用在因特網的TCP/IP協議之上,也可以用在其它網絡協議如IPX和NetBEUI 之上。
  SMB 一種客戶機/服務器、請求/響應協議。通過 SMB 協議,客戶端應用程序可以在各種網絡環境下讀、寫服務器上的文件,以及對服務器程序提出服務請求。此外通過 SMB 協議,應用程序可以訪問遠程服務器端的文件、以及打印機、郵件槽(mailslot)、命名管道(named pipe)等資源。
  在 TCP/IP 環境下,客戶機通過 NetBIOS over TCP/IP(或 NetBEUI/TCP 或 SPX/IPX)連接服務器。一旦連接成功,客戶機可發送 SMB 命令到服務器上,從而客戶機能夠訪問共享目錄、打開文件、讀寫文件,以及一切在文件系統上能做的所有事情。
  從 Windows 95 開始,Microsoft Windows 操作系統(operating system)都包括了客戶機和服務器 SMB 協議支持。Microsoft 為 Internet 提供了 SMB 的開源版本,即通用 Internet 文件系統 (CIFS)。與現有 Internet 應用程序如文件傳輸協議(FTP)相比, CIFS 靈活性更大。對於 UNIX 系統,可使用一種稱為 Samba 的共享軟件。
二、CIFS(Common Internet File System) 協議
CIFS 是一個新提出的協議,它使程序可以訪問遠程Internet計算機上的文件並要求此計算機的服務。CIFS 使用客戶/服務器模式。客戶程序請求遠在服務器上的服務器程序為它提供服務。服務器獲得請求並返回響應。CIFS是公共的或開放的SMB協議版本,並由Microsoft使用。SMB協議現在是局域網上用於服務器文件訪問和打印的協議。象SMB協議一樣,CIFS在高層運行,而不象TCP/IP協議那樣運行在底層。CIFS可以看做是應用程序協議如文件傳輸協議和超文本傳輸協議的一個實現。
三、NETBios協議
Netbios (網絡基本輸入/輸出系統)最初由 IBM,Sytek 作為API開發,使用戶軟件能使用局域網的資源。自從誕生,Netbios成為許多其他網絡應用程序的基礎。嚴格意義上,Netbios 是接入網絡服務的接口標准。
  Netbios 原來是作為THE網絡控制器為 IBM 局域網設計的,是通過特定硬件用來和網絡操作系統 連接的軟件層。Netbios經擴展,允許程序使用Netbios接口來操作IBM令牌環結構。Netbios 已被公認為工業標准,通常參照 Netbios-compatible LANs。
  它提供給網絡程序一套方法,相互通訊及傳輸數據。基本上,Netbios 允許程序和網絡會話。它的目的是把程序和任何類型的硬件屬性分開。它也使軟件開發員可以免除以下負擔:開發網絡錯誤修復,低層信息尋址和路由。使用Netbios接口,可以為軟件開發員做許多工作。
  Netbios使程序和局域網操作能力之間的接口標准化。有它們可以將程序細化到為OSI模型的哪一層所寫,使程序能移植到其他網絡上。在Netbios局域網環境下,計算機通過名字被系統知道。網絡中每台計算機都有通過不同方法編的永久性名稱。這些名稱將在下面做進一步討論。
  通過使用Netbios的數據報或廣播方式,在Netbios局域網上的pc機建立會話彼此聯絡。會話允許更多的信息被傳送,探測錯誤,和糾正。通信是在一對一的基礎上的。數據報或廣播方式允許一台計算機和多台其他的計算機同時通信,但信息大小受限。使用數據報或廣播方式沒有探測錯誤和糾正。然而,數據報通信可以不必建立一個會話。
  在這種環境下所有的通信以一種稱為“網絡控制塊“的格式提交給NetBIOS。內存中這些塊的分配依賴於用戶程序。這些“網絡控制塊“分配到域中,分別為輸入/輸出保留。
  在當今的環境中,NetBIOS是使用很普遍的協議。以太網,令牌環,IBM PC網都支持NetBIOS。在它原始版本中,它僅作為程序和網絡適配器的接口。從那以后,傳輸類功能加入NetBIOS,使它功能日益增多。
  在NetBIOS里,面向連接(tcp)和無連接(udp)通信均支持。它支持廣播和復播,支持三個分開的服務:命名,會話,數據報。
四、使用SMB協議訪問局域網中的共享文件
1、使用 jcifs的jar包: jcifs-1.3.14.jar,下載地址:http:// jcifs.samba.org/
2、本機地址:10.130.14.37,局域網中的地址:10.130.14.111,其共享文件:share(設置讀取、修改、完全控制的權限)
3、java代碼
package my.test;
import java.io.IOException;
import jcifs.smb.SmbAuthException;
import jcifs.smb.SmbException;
import jcifs.smb.SmbFileInputStream;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileOutputStream;
public class ReadShareFile
{
/**
* jcifs的開發方法類似java的文件操作功能,它的資源url定位:smb://{user}:{password}@{host}/{path},
* smb為協議名,user和password分別為共享文件機子的登陸名和密碼,@后面是要訪問的資源的主機名或IP地址。最后是資源的共享文件夾名稱和共享資源名。
* 例如smb://administrator:122122@192.168.0.22/test/response.txt。
* 
* 在JAVA程序中,使用如下方式獲得一個遠程共享文件(設置共享文件的權限——讀取、修改、完全控制)的句柄:SmbFile file = newSmbFile("smb://guest:1234@192.168.3.56/share/a.txt");
* 這里的句柄不僅限於遠程的共享文件,還可能是共享文件夾。
* isFile()方法和isDirectory()用來判斷這個句柄對應的資源的真實屬性。如果是共享文件夾
* ,通過調用它的list()方法將獲得其中資源的列表。
* List方法支持過濾器機制,有兩種過濾器可供使用,一種是SmbFileFilter,另一種是SmbFilenameFilter
* ,這兩個在jcifs中作為接口出現,你可以根據自己的需要派生出個性化的過濾器,實現接口中的accept方法,以滿足不同業務的需求。
*   
* SmbFileInputStream是smb文件的輸入流,它的功能是以流的方式打開一個SmbFile:SmbFileInputStream
* in = new SmbFileInputStream(file);SmbFileInputStream提供read方法,你可以從這個流中讀出遠程文件全部的內容。
* 
* @param args
* @throws IOException 
*/
@SuppressWarnings("static-access")
public static void main(String[] args)
{
   try
   {   
   //局域網共享文件,讀文件
   SmbFile smbFile = new SmbFile(
      "smb://administrator:dibindb@10.130.14.111/share/aa.txt");
    // 通過 smbFile.isDirectory();isFile()可以判斷smbFile是文件還是文件夾
    int length = smbFile.getContentLength();// 得到文件的大小
    byte buffer[] = new byte[length];
    SmbFileInputStream in = new SmbFileInputStream(smbFile); // 建立smb文件輸入流
    while ((in.read(buffer)) != -1)
    {
     System.out.write(buffer);
     System.out.println("\n"+buffer.length);
    }
    in.close();
   smbFile.delete();
  
   //局域網共享文件,寫文件
    SmbFile smbFileOut = new SmbFile("smb://administrator:dibindb@10.130.14.101/share/bb.txt");
    if(!smbFileOut.exists())
     smbFileOut.createNewFile();
    SmbFileOutputStream out = new SmbFileOutputStream(smbFileOut);
    out.write("abcdefw".getBytes());
    out.close();
    smbFileOut.delete();
   }
   catch (SmbAuthException e)
   {
    SmbException smb = new SmbException(1,false);
    System.out.println(e.getNtStatus()==smb.NT_STATUS_ACCESS_DENIED);
    for(int i=0;i<smb.NT_STATUS_CODES.length;i++)
    {
     System.out.println(smb.NT_STATUS_CODES[i]);
    }
    e.printStackTrace();
   }
   catch (IOException e)
   {
    e.printStackTrace();
   }
}
}
4、相關錯誤
(1)share只有讀取權限
jcifs.smb.SmbAuthException: Access is denied.
at jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:528)
at jcifs.smb.SmbTransport.send(SmbTransport.java:645)
at jcifs.smb.SmbSession.send(SmbSession.java:244)
at jcifs.smb.SmbTree.send(SmbTree.java:119)
at jcifs.smb.SmbFile.send(SmbFile.java:770)
at jcifs.smb.SmbFile.delete(SmbFile.java:2410)
at jcifs.smb.SmbFile.delete(SmbFile.java:2354)
at my.test.ReadShareFile.main(ReadShareFile.java:50)


如果通過路由器轉發需要在路由器上指定端口,139,445。

jcifs 無法訪問xp共享目錄問題 jcifs.smb.SmbAuthException
jcifs.smb.SmbAuthException: Logon failure: unknown user name or bad password.     
    at jcifs.smb.SmbSession.sessionSetup(SmbSession.java:273)     
    at jcifs.smb.SmbSession.send(SmbSession.java:225)     
    at jcifs.smb.SmbTree.treeConnect(SmbTree.java:147)     
    at jcifs.smb.SmbFile.connect(SmbFile.java:791)     
    at jcifs.smb.SmbFile.connect0(SmbFile.java:761)     
    at jcifs.smb.SmbFile.open0(SmbFile.java:816)     
    at jcifs.smb.SmbFile.open(SmbFile.java:845)     
    at jcifs.smb.SmbFileInputStream.<init>(SmbFileInputStream.java:69)     
    at jcifs.smb.SmbFileInputStream.<init>(SmbFileInputStream.java:62)     
    at jcifs.smb.SmbFileInputStream.<init>(SmbFileInputStream.java:49)     
    at cn.com.egova.dti.dao.AdjunctManager.main(AdjunctManager.java:188)    


解決辦法:工具-->文件夾選項-->查看-->使用簡單文件共享,去掉勾選即可


通過域名獲得IP和判斷是否為IP地址
		   java.net.InetAddress[] x= java.net.InetAddress.getAllByName("www.aaa.com");
		   String ip = "";
		   if(x.length>0){
			   ip = x[0].toString().split("/")[1];
		   }
		    /**  
		     * IP地址正則表達式 ((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))  
		     */  
		    String IPADDRESS = "((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))";
	        Pattern pattern = Pattern.compile(IPADDRESS);
	        Matcher matcher = pattern.matcher(x.toString());
	        boolean isIp = matcher.matches();



創建文件夾
		
try {
	if (!smbTempFile.isDirectory())
	smbTempFile.mkdirs();
} catch (SmbException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM