Smbclient介紹

Just4life發表於2014-12-24

1      Smbclient介紹

Smbclient(samba client)是基於SMB協議的,用於存取共享目標的客戶端程式。

SMB 協議介紹 :

伺服器資訊塊(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 的共享軟體。

SMB 定義了兩級安全保護:

共享級保護(Share Level Protection)應用於伺服器共享目錄級。每個共享目錄都需要提供一個訪問口令。只有口令通過,客戶機才能訪問所有共享檔案。

使用者級保護(Usr Level Protection)應用於共享目錄中的單獨檔案,基於使用者訪問許可權。每個使用者(客戶機)必須登入伺服器並且獲得伺服器的認證許可。一旦認證通過,客戶 機會獲得一個 UID 。在後來客戶機訪問伺服器的過程中都需要使用該 UID 。

2      Smbclient命令使用技巧

2.1       smbclient 功 能說明:

可存取SMB/CIFS伺服器的使用者端程式。

2.1.1         語法 :

smbclient [網路資源][密碼][-EhLN][-B][-d<排錯層級>][-i<範圍>][-I][-l<記錄檔案>] [-M][-n][-O<連線槽選項>][-p][-R<名稱解析順序>][-s<目錄>][-t<伺服器字 碼>][-T][-U<使用者名稱稱>][-W<工作群組>]補充說明:SMB與CIFS為伺服器通訊協議,常用於 Windows95/98/NT等系統。smbclient可讓Linux系統存取Windows系統所分享的資源。

2.1.2         引數:

網路資源 網路資源的格式為//伺服器名稱/資源分享名稱。

密碼 輸入存取網路資源所需的密碼。

-B 傳送廣播資料包時所用的IP地址。

-d <排錯層級> 指定記錄檔案所記載事件的詳細程度。

-E 將資訊送到標準錯誤輸出裝置。

-h 顯示幫助。

-i <範圍> 設定NetBIOS名稱範圍。

-I 指定伺服器的IP地址。

-l <記錄檔案> 指定記錄檔案的名稱。

-L 顯示伺服器端所分享出來的所有資源。

-M 可利用WinPopup協議,將資訊送給選項中所指定的主機。

-n 指定使用者端所要使用的NetBIOS名稱。

-N 不用詢問密碼。

-O <連線槽選項> 設定使用者端TCP連線槽的選項。

-p 指定伺服器端TCP連線埠編號。

-R <名稱解析順序> 設定NetBIOS名稱解析的順序。

-s <目錄> 指定smb.conf所在的目錄。

-t <伺服器字碼> 設定用何種字元碼來解析伺服器端的檔名稱。

-T 備份伺服器端分享的全部檔案,並打包成tar格式的檔案。

-U <使用者名稱稱> 指定使用者名稱稱。

-W <工作群組> 指定工作群組名稱。

2.2       smbclient 使 用舉例:

2.2.1      列出某個 IP 地 址所提供的共享資料夾

smbclient -L 198.168.0.1 -U username%password

2.2.2      像 FTP 客 戶端一樣使用 smbclient

smbclient //192.168.0.1/tmp  -U username%password

執行smbclient命令成功後,進入smbclient環境,出現提示符: smb:/>

這裡有許多命令和ftp命令相似,如cd 、lcd、get、megt、put、mput等。通過這些命令,我們可以訪問遠端主機的共享資源。

2.2.3      直接一次性使用 smbclient 命 令

smbclient -c "ls"  //192.168.0.1/tmp  -U username%password

smbclient -c "get test.txt" //192.168.0.1/tmp -U username%password

3      Smbclient開發技巧

3.1       常用函式介紹

Smbclient提供了兩種外部介面,一種是SMBCCTX資訊結構體中的函式指標,輸入及輸出中含有smbclient自定義的變數;另一種是 smbc族的介面,輸入及輸出均為系統基本變數,其實質是通過對SMBCCTX中的函式指標的封裝來實現的。

3.1.1       Smbc 族 函式:

int smbc_init(smbc_get_auth_data_fn fn , int debug) ;

初始化samba client庫,此函式必須在所有其他smbc族API被呼叫前使用。

引數:

fn *:*用於傳遞SMB協議所需的基本資訊;

提供一個簡單的fn實現(其中server為samba伺服器地址,share為共享目錄標識,workgroup為所在域的域 名,username為使用者名稱,password為登入密碼):

static void auth_fn(const char *server, const char *share, char *workgroup, int wgmaxlen,
                char *username, int unmaxlen, char *password, int pwmaxlen)
{
    
    strncpy(workgroup, g_workgroup, wgmaxlen - 1);
    strncpy(username, g_username, unmaxlen - 1);
    strncpy(password, g_password, pwmaxlen - 1);
    strcpy(g_server, server);
    strcpy(g_share, share);
//    fprintf(stderr,"server[%s],share[%s]/n",server,share);
}

debug *:*除錯資訊等級(本人建議值0-10);

返回值:

0為成功,<0為失敗,錯誤資訊可通過errno獲取。

int smbc_open(const char *furl, int flags, mode_t mode);

開啟共享伺服器上的一個檔案,使用方法請參考open函式。

int smbc_creat(const char *furl, mode_t mode);

在共享伺服器上建立一個檔案,使用方法請參考open函式。

ssize_t smbc_read(int fd, void *buf, size_t bufsize);

使用一個開啟的檔案控制程式碼來讀取共享伺服器上的檔案,使用方法請參考read函式。

ssize_t smbc_write(int fd, void *buf, size_t bufsize);

使用一個開啟的檔案控制程式碼向共享伺服器上的檔案寫資料,使用方法請參考write函式。

off_t smbc_lseek(int fd, off_t offset, int whence);

移動檔案的讀寫位置,使用方法請參考lseek函式。

int smbc_close(int fd);

關閉一個開啟的檔案控制程式碼,使用方法請參考close函式。

int smbc_unlink(const char *furl);

刪除一個共享伺服器上的檔案或者資料夾,使用方法請參考unlink函式。

int smbc_rename(const char *ourl, cones char *nurl);

重新命名(或移動)共享目錄上的檔案或者資料夾,使用方法請參考rename函式。

int smbc_opendir(const char *durl);

開啟共享伺服器上的資料夾,使用方法請參考opendir函式。

int smbc_closedir(int dh);

關閉一個開啟的資料夾控制程式碼,使用方法請參考closedir函式。

struct smbc_dirent* smbc_readdir(unsigned int dh);

讀取共享伺服器上的資料夾資訊,使用方法請參考readdir函式。

off_t smbc_telldir(int dh);

獲取資料夾流當前的讀取位置,使用方法請參考telldir函式。

int smbc_mkdir(const char *durl, mode_t mode);

在共享伺服器上建立一個資料夾。

引數:

durl *:*路徑

mode *:*訪問許可權

返回值:

0為成功,<0為失敗,失敗資訊可通過errno來獲取。

int smbc_rmdir(const char *durl);

刪除共享伺服器上的一個資料夾。

引數:

durl *:*路徑

返回值:

0為成功,<0為失敗,失敗資訊可通過errno來獲取。

int smbc_stat(const char *url, struct stat *st);

獲取共享伺服器上一個檔案或者資料夾的所有資訊,使用方法請參考stat函式。

int smbc_fstat(int fd, struct stat *st);

通過檔案控制程式碼來獲取共享伺服器上一個檔案的所有資訊,使用方法請參考fstat函式。

int smbc_chown(const char *url, uid_t owner, gid_t group);

修改共享伺服器上檔案或者資料夾的所有者資訊,使用方法請參考chown函式。

int smbc_chmod(const char *url, mode_t mode);

修改共享伺服器上的檔案的許可權,使用方法請參考chmod函式。

int smbc_utimes(const char *url, struct timeval *tbuf);

修改共享伺服器上的檔案的最後修改時間,使用方法請參考utimes函式。

範例:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <libsmbclient.h>

#define MAX_BUFF_SIZE   255
char g_workgroup[MAX_BUFF_SIZE];
char g_username[MAX_BUFF_SIZE];
char g_password[MAX_BUFF_SIZE];
char g_server[MAX_BUFF_SIZE];
char g_share[MAX_BUFF_SIZE];
SMBCCTX * context;
SMBCSRV * srv;

static void auth_fn(const char *server, const char *share, char *workgroup, int wgmaxlen,
                char *username, int unmaxlen, char *password, int pwmaxlen)
{
    
    strncpy(workgroup, g_workgroup, wgmaxlen - 1);
    strncpy(username, g_username, unmaxlen - 1);
    strncpy(password, g_password, pwmaxlen - 1);
    strcpy(g_server, server);
    strcpy(g_share, share);
//    fprintf(stderr,"server[%s],share[%s]/n",server,share);
}

int main(int argc,char* argv[]){
    int err = -1;
    int dh = 0;
    int fd = -1;
    int buflen = 0;
    char buffer[1024] = {0};
    char url[MAX_BUFF_SIZE] = {0};
    char file[MAX_BUFF_SIZE] = {0};
    struct smbc_dirent* dirptr;
    
    bzero(g_workgroup,MAX_BUFF_SIZE);
    bzero(url,MAX_BUFF_SIZE);
    printf("%s/n",smbc_version());
    
    strncpy(g_workgroup,argv[1],strlen(argv[1]));
    strncpy(g_username,argv[2],strlen(argv[2]));
    strncpy(g_password,argv[3],strlen(argv[3]));
    strncpy(url,argv[4],strlen(argv[4]));
    if(url[strlen(url)-1] != '/'){
        strcat(url,"/");
    }
    err = smbc_init(auth_fn, 10);
    if(err < 0){
        perror("smbc_init error");
    }else{
        dh = smbc_opendir(url);
        while((dirptr = smbc_readdir(dh)) != NULL){
            bzero(file,MAX_BUFF_SIZE);
            printf("dirptr->name[%s],dirptr->smbc_type[%d]/n",dirptr->name,dirptr->smbc_type);
            if(dirptr->smbc_type == SMBC_FILE){
                bzero(buffer,1024);
                strncpy(file,url,strlen(url));
                strncat(file,dirptr->name,dirptr->namelen);
                printf("%s/n",file);
                if((fd = smbc_open(file,O_RDONLY,0666)) > 0){
                    while((buflen = smbc_read(fd,buffer,1024)) > 0){
//                        printf("buffer[%s]/n",buffer);
                    }
                    smbc_close(fd);
                }
            }
        }
        smbc_closedir(dh);
//        printf("smbc_rmdir(url)[%d]/n",smbc_rmdir(url));
    }
    return err;
}

 

3.1.2       函式指標:

SMBCCTX *smbc_new_context(void);

建立一個新的SMBCCTX結構體。

返回值:

SMBCCTX結構體指標,返回NULL為失敗。錯誤資訊可通過errno獲取。

int smbc_free_context(SMBCCTX *context, int shutdown_ctx);

刪除一個SMBCCTX結構體。

引數:

context *:*已建立的SMBCCTX結構體指標。

shutdown_ctx *:*強制刪除標識。

                      為1時,為強制刪除;

為0時,若此context與共享伺服器的連線仍在使用或者有檔案仍被開啟,則刪除context失敗;

返回值:

0為成功,1為失敗。錯誤資訊可通過errno獲取。

SMBCCTX *smbc_init_context(SMBCCTX * context);

初始化SMBCCTX結構體。

引數:

context *:*已建立的SMBCCTX結構體執政。

返回值:

成功初始化的SMBCCTX結構體指標,若返回值NULL則為初始化失敗。錯誤資訊可通過errno獲取。

SMBCCTX * smbc_set_context(SMBCCTX * new_context);

設定(或重置)SMBCCTX結構體資料。

引數:

new_context *:*已建立的SMBCCTX結構體指標。

返回值:

被設定前的原始SMBCCTX結構體指標。

SMBCFILE *(*open) (SMBCCTX *c, const char *fname, int flags, mode_t mode);

開啟共享伺服器上的一個檔案。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

fname *:*檔案路徑;

flags *:*開啟方式;

mode *:*檔案許可權

返回值 :

成功開啟的檔案控制程式碼,若<=0為失敗,錯誤資訊可通過errno獲取。

SMBCFILE *(*creat)(SMBCCTX *c, const char *path, mode_t mode);

在共享伺服器上的建立一個檔案。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

path *:*檔案路徑;

mode *:*檔案許可權

返回值 :

成功建立的檔案控制程式碼,若<=0為失敗,錯誤資訊可通過errno獲取。

ssize_t (*read)(SMBCCTX *c, SMBCFILE *file, void *buf, size_t count);

使用一個開啟的檔案控制程式碼來讀取共享伺服器上的檔案。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

file *:*檔案控制程式碼;

buf *:*存放讀取到的資料的記憶體指標;

count *:*讀取長度

返回值 :

實際讀取到的位元組數,如果返回0,表示已到達檔案尾或者無可讀取的資料,此外檔案讀寫位置會隨讀取到的位元組移動,若返回-1表示有錯誤發生,錯誤信 息可通過errno獲取。 

ssize_t (*write)(SMBCCTX *c, SMBCFILE *file, void *buf, size_t count);

使用一個開啟的檔案控制程式碼向共享伺服器上的檔案寫資料。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

file *:*檔案控制程式碼;

buf *:*需要寫入的資料的指標;

count *:*寫入資料的長度

返回值 :

實際寫入的位元組數,若返回-1表示有錯誤發生,錯誤資訊可通過errno獲取。

int (*unlink)(SMBCCTX *c, const char *fname);

刪除一個共享伺服器上的檔案或者資料夾。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

fname *:*指定路徑

返回值 :

0為成功,-1為失敗,錯誤資訊可通過errno獲取。

int (*rename)(SMBCCTX *ocontext, const char *oname, SMBCCTX *ncontext, const char *nname);

重新命名(或移動)共享目錄上的檔案或者資料夾。

引數:

ocontext *:*已初始化(或設定)的SMBCCTX結構體指標;

oname *:*源路徑;

ncontext *:*已初始化(或設定)的SMBCCTX結構體指標;

nname *:*目標路徑

返回值 :

0為成功,-1為失敗,錯誤資訊可通過errno獲取。

off_t (*lseek)(SMBCCTX *c, SMBCFILE * file, off_t offset, int whence);

移動檔案的讀寫位置。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

file *:*檔案控制程式碼;

offset *:*位移量;

whence *:*位移起始位置(SEEK_SET,SEEK_CUR,SEEK_END)

返回值 :

當前檔案的讀寫位置,若返回-1表示有錯誤發生,錯誤資訊可通過errno獲取。

int (*stat)(SMBCCTX *c, const char *fname, struct stat *st);

獲取共享伺服器上一個檔案或者資料夾的所有資訊。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

fname *:*路徑;

st *:*檔案屬性結構體

返回值 :

0為成功,-1為失敗,錯誤資訊可通過errno獲取。

int (*fstat)(SMBCCTX *c, SMBCFILE *file, struct stat *st);

通過檔案控制程式碼來獲取共享伺服器上一個檔案的所有資訊。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

file *:*檔案控制程式碼;

st *:*檔案屬性結構體

返回值 :

0為成功,-1為失敗,錯誤資訊可通過errno獲取。

int (*close_fn)(SMBCCTX *c, SMBCFILE *file);

關閉一個開啟的檔案控制程式碼。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

file *:*檔案控制程式碼;

返回值 :

0為成功,-1為失敗,錯誤資訊可通過errno獲取。

SMBCFILE *(*opendir)(SMBCCTX *c, const char *fname);

開啟共享伺服器上的資料夾。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

fname *:*資料夾路徑;

返回值 :

成功開啟的資料夾控制程式碼,若NULL為失敗,錯誤資訊可通過errno獲取。

int (*closedir)(SMBCCTX *c, SMBCFILE *dir);

關閉一個開啟的資料夾控制程式碼。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

fname *:*資料夾控制程式碼;

返回值 :

0為成功,-1為失敗,錯誤資訊可通過errno獲取。

struct smbc_dirent *(*readdir)(SMBCCTX *c, SMBCFILE *dir);

讀取共享伺服器上的資料夾資訊。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

dir *:*資料夾控制程式碼;

返回值 :

下個資料夾進入點,若NULL為失敗或讀取到目錄檔案尾,錯誤資訊可通過errno獲取。

int (*mkdir)(SMBCCTX *c, const char *fname, mode_t mode);

在共享伺服器上建立一個資料夾。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

fname *:*資料夾路徑;

mode *:*許可權;

返回值 :

0為成功,-1為失敗,錯誤資訊可通過errno獲取。

int (*rmdir)(SMBCCTX *c, const char *fname);

刪除共享伺服器上的一個資料夾。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

fname *:*資料夾路徑;

返回值 :

0為成功,-1為失敗,錯誤資訊可通過errno獲取。

off_t (*telldir) (SMBCCTX *c, SMBCFILE *dir);

獲取資料夾流當前的讀取位置。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

dir *:*資料夾控制程式碼;

返回值:

下一個讀取位置,-1表示有錯誤發生,錯誤資訊可通過errno獲取。

int (*chmod)(SMBCCTX *c, const char *fname, mode_t mode);

修改共享伺服器上的檔案的許可權。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

fname *:*資料夾路徑;

mode *:*許可權;

返回值 :

0為成功,-1為失敗,錯誤資訊可通過errno獲取。

int (*utimes)(SMBCCTX *c, const char *fname, struct timeval *tbuf);

修改共享伺服器上的檔案的最後修改時間。

引數:

c *:*已初始化(或設定)的SMBCCTX結構體指標;

fname *:*資料夾路徑;

tbuf *:*時間結構體;

返回值 :

0為成功,-1為失敗,錯誤資訊可通過errno獲取。 

範例:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <libsmbclient.h>

#define MAX_BUFF_SIZE   255
char g_workgroup[MAX_BUFF_SIZE];
char g_username[MAX_BUFF_SIZE];
char g_password[MAX_BUFF_SIZE];
char g_server[MAX_BUFF_SIZE];
char g_share[MAX_BUFF_SIZE];
SMBCCTX * context;
SMBCSRV * srv;
//smbc_get_cached_srv_fn get_srv;

static void auth_fn(const char *server, const char *share, char *workgroup, int wgmaxlen,
                char *username, int unmaxlen, char *password, int pwmaxlen)
{
    
    strncpy(workgroup, g_workgroup, wgmaxlen - 1);
    strncpy(username, g_username, unmaxlen - 1);
    strncpy(password, g_password, pwmaxlen - 1);
    strcpy(g_server, server);
    strcpy(g_share, share);
//    fprintf(stderr,"server[%s],share[%s]/n",server,share);
}

int main(int argc, char* argv[]){
    SMBCFILE* sfd;
    SMBCFILE* fd;
    int localfd = -1,readlen = -1;
    
    struct smbc_server_cache * getServerCacheData;
    char buff[1024*1024*4] = {0};
    char url[MAX_BUFF_SIZE] = {0};
    char file[MAX_BUFF_SIZE] = {0};
    struct smbc_dirent* dirptr;
    bzero(g_workgroup,MAX_BUFF_SIZE);
    bzero(url,MAX_BUFF_SIZE);
    printf("%s/n",smbc_version());
    
    strncpy(g_workgroup,argv[1],strlen(argv[1]));
    strncpy(g_username,argv[2],strlen(argv[2]));
    strncpy(g_password,argv[3],strlen(argv[3]));
    strncpy(url,argv[4],strlen(argv[4]));
    if(url[strlen(url)-1] != '/'){
        strcat(url,"/");
    }
    context = smbc_new_context();
    if(context != NULL){
        context->debug = 10;
        context->callbacks.auth_fn = auth_fn;
        context->options.one_share_per_server = 1;
    
        if(!smbc_init_context(context)){
            perror("smbc_init_context failed");
            smbc_free_context(context,1);
            return -1;
        }
        
        sfd = context->opendir(context,url);
        struct smbc_dirent dirptr1;
        while((dirptr = context->readdir(context,sfd)) != NULL){
            if(dirptr->smbc_type == SMBC_FILE){
                printf("name[%s]/n",dirptr->name);
                strncpy(file,url,strlen(url));
                strncat(file,dirptr->name,dirptr->namelen);
                if((fd = context->open(context,file,O_RDONLY,0666)) > 0){
                    context->close_fn(context,fd);
                }
            }
        }
        context->closedir(context,sfd);
    }
    return 0;
}

 

4          Smbclient 使 用的個人小結

4.1       Smbclient 編 程需要注意的地方:

4.1.1     使用smbclient程式設計需要用到的庫,/usr/lib/libsmbclient.so 或者/usr/lib/libsmbclient.a。

4.1.2     smbclient中,同一個共享目錄下的所有資料互動,控制訊息使用的有且只有一個connection連線(通過設定 one_share_per_server屬性,可將同一個共享伺服器下所有操作及資料互動都使用同一個connection連線)。

4.1.3     smbclient向samba伺服器的連線方式:smbclient的連線請求是在呼叫除初始化設定外的所有API介面時才發起的。這些API中,首先 會查詢當前srv下是否有可用的連線,若有則使用當前可用連線,若沒有可用連線則建立新的連線。

4.1.4     smbclient的控制程式碼是一個包含與伺服器連線fd,請求檔名,共享伺服器控制程式碼等連線資訊的集合。

4.1.5     smbclient的重連機制:smbclient的內部是不提供重連機制的,也就是說,若一個請求超時後,API將直接返回錯誤資訊。由本節點第二點可 知,在應用層下一次呼叫API時,smbclient層會向samba伺服器再次發出連線請求。

4.1.6     smbclient的smbc族函式使用時需要注意的的地方:

                                    i.             由A可知,smbc_init函式實質 上是對smbc_new_context()和smbc_init_context(SMBCCTX *context)進行了封裝,而smbc_init函式並沒有提供引數來指定smbc_new_context和smbc_init_context使 用的context指標。因此,smbc_init函式初始化的是smbclient庫中的一個全域性變數SMBCCTX *statcont。我們知道當一個程式中多次呼叫同一個庫檔案時,庫檔案的全域性變數的地址是唯一的,也就是說,若我們使用smbc族API來對 smbclient進行多執行緒程式設計是不可行的。

                                  ii.             由libsmbclient.h中的宣告 可知,smbc族的API沒用提供對SMBCCTX結構體的引數設定介面。也就是說這種API不適合有特殊需求的程式(例如需要獲取的資料為 urlcontext型別,或者需要指定同一個共享伺服器下的所有共享資料夾都只使用一個連線等)

4.1.7     由SMB協議可知,基於SMB協議的資料互動必須遵循 連線->傳送命令->接收資料 ->傳送命令->......->斷開連線 的阻塞通訊模式,又因為當smbclient是以一個連線至少對應一個共享檔案的方式來進行通訊的,所以若簡單的對smbclient使用多執行緒操作,會 出現資料混亂的情況,導致不可預期的錯誤。

4.1.8     管理SMBCCTX的一些小技巧:

                                    i.             首先,我們需要使用SMBCCTX結構 體函式指標API。

                                  ii.             SMBCCTX結構體中提供了一個 callbacks結構體,我們可以通過使用其中的部分函式來獲取SMBCCTX的一些狀態,並進行管理。

                                 iii.             get_cached_srv_fn:通 過伺服器地址、共享目錄名、使用者名稱、所在域名來獲取SMBCCTX中符合條件的srv,返回值將用於下面的這些函式呼叫。

                                iv.             check_server_fn:使用這個函 數可以檢視指定的server的健康狀態(這裡特別提一下,在samba3.0.X的版本中,此函式是通過向伺服器端傳送自定義PING包來確定當前 server的連線是否正常,以此來判斷server的健康狀態的;而samba3.2.4中,則是通過當前連線所用的fd所對應的 socket_addr結構體是否存在來判斷server的健康狀態的。或許設計者的出發點不同,但samba3.0.X更加適合我們現在的專案)。

                                  v.             remove_unsed_server_fn: 刪除當前沒有使用的srv

                                vi.             remove_cached_srv_fn: 刪除快取池指定的srv。

                               vii.             purge_cached_fn:刪除快取池 所有的srv

4.2       多執行緒程式設計的解決方案:

根 據samba官方訊息,3.0.X版本的libsmbclient設計並未考慮成執行緒安全,因此最佳的多執行緒呼叫方式應該為加鎖方式,至於新版本中是否為 執行緒安全,以及其使用方式,持續關注中。。。