SMB协议实现局域网之间文件传输
一、背景
为解决历史资料存储位置分散(局域网不同服务器),管理人员众多,资料管理仍保留在传统ftp管理阶段等问题,开展对历史资料管理功能,具体需求功能因为保密协议就不在阐述,本次只针对技术局域网之间传输技术进行讨论;
二、技术对比
访问局域网中共享信息有两种方式,网络映射、SMB协议访问,这两种都是比较成熟的技术了。
序号 |
指标 |
网络映射 |
SMB协议 |
1 |
传输 速度 |
传输效率主要跟局域网网络传输效率有关,传输效率快。 |
在文件传输过程中,创建文件会导致高协议开销和较高的文件系统开销。 对于大型文件传输,这些成本仅出现一次。 当传输大量小文件时,成本是重复的,导致传输速度缓慢; |
2 |
第一次访问 |
必须在本地创建映射 |
通过用户名、密码直接可以访问 |
3 |
访问人数 |
无限制 |
无限制 |
4 |
系统兼容性 |
兼容windows、Linux系统 |
SMB协议只能在windows系统之间传输,如果是Linux主机,需要对linux主机安装Samba |
5 |
传输是否加密 |
加密 |
加密 |
6 |
安全性 |
如果在一台服务器映射多个磁盘会有安全隐患;不能创建同一个ip下的不通共享目录 |
局域网内所有电脑都可以通过smb协议进行访问,有安全隐患。 |
三、SMB协议介绍
SMB(Server Message Block)是由微软开发的一种软件程序级的网络传输协议,主要用来使得一个网络上的计算机共享计文件、打印机、串行端口和通信等资源。它也提供认证的进行进程间通讯机能。通过Unix服务器厂商从新开发后,它能够用于链接Unix服务器和Windows客户机,执行打印和文件共享等任务。
SMB一开始的设计是在NetBIOS协议上运行的(而NetBIOS自己则运行在NetBEUI、IPX/SPX或TCP/IP协议上)。从Windows2000开始,微软引入SMB Direct Over TCP,从新命名为 CIFS(Common Internet File System),并打算将它与NetBIOS相脱离,试图使它成为Internet上计算机之间相互共享数据的一种标准。CIFS是公开或开放的SMB协议版本。s
四、SMB协议实现常用功能
参考的:https://www.cjavapy.com/article/395/
基础环境:.net 4.5以上
smb包:SharpCifs.Core,
(1)windows创建共享目录
创建共享目录这块不是重点,可参考如下网站:
https://jingyan.baidu.com/article/0bc808fc1f06765ad485b987.html
(2)SMB协议连接共享目录
/// <summary>
/// 测试连接是否通
/// </summary>
/// <param name="returnMessag"></param>
/// <param name="ip"></param>
/// <param name="name"></param>
/// <param name="pwd"></param>
/// <param name="folder"></param>
/// <returns></returns>
public bool GetCon(string ip, string name, string pwd, string folder)
{
SharpCifs.Config.SetProperty("jcifs.smb.client.lport", "8137");
var auth2 = new NtlmPasswordAuthentication(ip, name, pwd);
SmbFile outDirFile = new SmbFile("smb://" + ip + "/" + folder + "/", auth2);
bool returnMessag = outDirFile.Exists();
return returnMessag;
}
(3)通过SMB协议获取文件信息
#region 获取文档信息,这块使用了递归
/// <summary>
/// 获取文档信息
/// </summary>
/// <param name="liststring"></param>
/// <param name="ip_folder"></param>
/// <param name="name"></param>
/// <param name="pwd"></param>
/// <param name="ip"></param>
public void getListString(List<FileClass> liststring, string ip_folder, string name, string pwd, string ip, string parentdocid)
{
SmbFile outDirFile = new SMBClass().GetSmbFile(ip_folder, name, pwd, ip);
var epocDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
string msg = "";
foreach (SmbFile item in outDirFile.ListFiles())
{
try
{
FileClass files = new FileClass();
files.IsFileDoc = false;
var type = item.IsFile() ? "file" : "dir";
var filename = "";// item.GetName();//文件名称
if (type == "dir")
{
filename = FilesClass.getFiles(item.ToString(), type);
files.IsFileDoc = true;
files.FileSize = 0;
}
else
{
filename = FilesClass.getFiles(item.ToString(), type);
files.FileSize = item.Length();
files.DocFileType = FilesClass.getFileExt(filename);
}
DateTime tm = item.GetLocalCreateTime();
files.CreationDate = tm;
files.DocName = filename;
files.DocID = Guid.NewGuid().ToString().Trim();
files.DocType = 2;
files.ParentDocid = parentdocid;
files.DocFileNameWithPath = item.ToString().Replace("%23", "#");
files.FileFullPath = item.ToString().Replace("smb://" + ip + "/", "").Replace("%23", "#");///文档全路径,解决特殊字符问题;
liststring.Add(files);
if (type == "dir")
{
getListString(liststring, item.ToString(), name, pwd, ip, files.DocID);///递归循环
}
}
catch (Exception ex)
{
/// new NoteClass().WriteNoteToTxt("错误:" + ex.Message);
}
}
}
#endregion
(4)通过SMB协议判断文件是否存在、删除文件信息
调用方法:
SmbFile file = new SMBClass().GetSmbFile(filepyth, username, pwd, ip);//获取SMBfiles
bool returnMessag = file.Exists();
if (returnMessag) {file.Delete();}
/// <summary>
/// 获取文件信息
/// </summary>
/// <param name="returnMessag"></param>
/// <param name="ip_folder"></param>
/// <param name="name"></param>
/// <param name="pwd"></param>
/// <param name="folder"></param>
/// <returns></returns>
public SmbFile GetSmbFile(string ip_folder, string name, string pwd, string ip)
{
SharpCifs.Config.SetProperty("jcifs.smb.client.lport", "8137");
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(ip, name, pwd);
ip_folder = ip_folder.Replace("#", "%23");//特殊字符处理
Uri url = new Uri(ip_folder);
SmbFile outDirFile = new SmbFile(url, auth);
return outDirFile;
}
(5)通过SMB协议下载
public SmbFileInputStream getsmb(string filepath, string ip, string name, string pwd)
{
try
{
var ip_folder = filepath;// "smb://192.168.1.18/wp/2.txt";///文件信息
SmbFile file = new SMBClass().GetSmbFile(ip_folder, name, pwd, ip);//获取SMBfiles
int length = file.GetContentLength();//得到文件的大小
byte[] buffer = new byte[length];
SmbFileInputStream stream = new SmbFileInputStream(file); //建立smb文件输入流
return stream;
}
catch (Exception ex)
{
return null;
}
}
(6)通过SMB协议上传
string url_local = @"D:\Users\Desktop\码\demo\SharpCifs.Core.dll";//本地文件
String URL_remote = "smb://192.169.1.1/test/SharpCifs.Core.dll";//服务器文件
///1、创建映射
String domainip = "192.169.1.1";///访问用户信息
String userName = "test";//远程用户
String passWord = "test";//密码
String fileName = "test";///文件信息
SharpCifs.Config.SetProperty("jcifs.smb.client.lport", "8137");
var auth2 = new NtlmPasswordAuthentication(domainip, userName, passWord);
SmbFile smbfile = new SmbFile(URL_remote, auth2);
//2、获取本地文件路径
FilePath pathes = new FilePath(url_local);
InputStream ins = new FileInputStream(pathes);
//3、开始上传
if (smbfile.Exists())
{
MessageBox.Show("已存在。");
}
else
{
smbfile.Connect();
OutputStream outs = new SmbFileOutputStream(smbfile);
byte[] buffer = new byte[4096];
int len = 0; //读取长度
while ((len = ins.Read(buffer, 0, buffer.Length)) != -1)
{
outs.Write(buffer, 0, len);
}
outs.Flush(); //刷新缓冲的输出流
MessageBox.Show("上传完成。");
}