|
|
|
@ -12,24 +12,6 @@ namespace TRI_TCP_Server
|
|
|
|
|
{
|
|
|
|
|
public class Run
|
|
|
|
|
{
|
|
|
|
|
//绑定本地IP
|
|
|
|
|
private static string Ip = "172.17.208.203";
|
|
|
|
|
//绑定端口
|
|
|
|
|
private static string Port = "5001";
|
|
|
|
|
public static void Main(string[] args)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
BeginListening(Ip, Port);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("监听服务器出错: " + ex.Message.ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Console.ReadKey();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
|
|
|
|
|
private static Thread threadWatch = null;
|
|
|
|
@ -37,27 +19,32 @@ namespace TRI_TCP_Server
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 开始监听
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="localIp"></param>
|
|
|
|
|
/// <param name="localPort"></param>
|
|
|
|
|
public static void BeginListening(string localIp, string localPort)
|
|
|
|
|
public static void Main()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//创建服务端负责监听的套接字,参数(使用IPV4协议,使用流式连接,使用Tcp协议传输数据)
|
|
|
|
|
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
|
//获取Ip地址对象
|
|
|
|
|
IPAddress address = IPAddress.Parse(localIp);
|
|
|
|
|
//创建包含Ip和port的网络节点对象
|
|
|
|
|
IPEndPoint endpoint = new IPEndPoint(address, int.Parse(localPort));
|
|
|
|
|
//将负责监听的套接字绑定到唯一的Ip和端口上
|
|
|
|
|
socketWatch.Bind(endpoint);
|
|
|
|
|
//设置监听队列的长度
|
|
|
|
|
socketWatch.Listen(10);
|
|
|
|
|
//创建负责监听的线程,并传入监听方法
|
|
|
|
|
threadWatch = new Thread(WatchConnecting);
|
|
|
|
|
threadWatch.IsBackground = true;//设置为后台线程
|
|
|
|
|
threadWatch.Start();//开始线程
|
|
|
|
|
//ShowMgs("服务器启动监听成功");
|
|
|
|
|
Console.WriteLine("服务器启动监听成功");
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//创建服务端负责监听的套接字,参数(使用IPV4协议,使用流式连接,使用Tcp协议传输数据)
|
|
|
|
|
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
|
//获取Ip地址对象
|
|
|
|
|
IPAddress address = IPAddress.Parse("0.0.0.0");
|
|
|
|
|
//创建包含Ip和port的网络节点对象
|
|
|
|
|
IPEndPoint endpoint = new IPEndPoint(address, int.Parse("5001"));
|
|
|
|
|
//将负责监听的套接字绑定到唯一的Ip和端口上
|
|
|
|
|
socketWatch.Bind(endpoint);
|
|
|
|
|
//设置监听队列的长度
|
|
|
|
|
socketWatch.Listen(10);
|
|
|
|
|
//创建负责监听的线程,并传入监听方法
|
|
|
|
|
threadWatch = new Thread(WatchConnecting);
|
|
|
|
|
threadWatch.IsBackground = true;//设置为后台线程
|
|
|
|
|
threadWatch.Start();//开始线程
|
|
|
|
|
//ShowMgs("服务器启动监听成功");
|
|
|
|
|
Console.WriteLine("服务器启动监听成功");
|
|
|
|
|
Console.ReadKey();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"监听异常:{ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -71,11 +58,11 @@ namespace TRI_TCP_Server
|
|
|
|
|
Socket connection = socketWatch.Accept();
|
|
|
|
|
if (connection.Connected)
|
|
|
|
|
{
|
|
|
|
|
//将与客户端通信的套接字对象connection添加到键值对集合中,并以客户端Ip做为健
|
|
|
|
|
//将与客户端通信的套接字对象connection添加到键值对集合中,并以客户端Ip做为健,唯一标志符号
|
|
|
|
|
dict.Add(connection.RemoteEndPoint.ToString(), connection);
|
|
|
|
|
|
|
|
|
|
//创建通信线程
|
|
|
|
|
ParameterizedThreadStart pts = new ParameterizedThreadStart(RecMsg);
|
|
|
|
|
ParameterizedThreadStart pts = new ParameterizedThreadStart(RecvMsg);
|
|
|
|
|
Thread thradRecMsg = new Thread(pts);
|
|
|
|
|
thradRecMsg.IsBackground = true;
|
|
|
|
|
thradRecMsg.Start(connection);
|
|
|
|
@ -91,97 +78,55 @@ namespace TRI_TCP_Server
|
|
|
|
|
private static void test(object socketPara)
|
|
|
|
|
{
|
|
|
|
|
Socket socket = socketPara as Socket;
|
|
|
|
|
while (true)
|
|
|
|
|
string sendDir = @"D:\ServerDir";
|
|
|
|
|
string[] recv = GetFileSystemEntries(sendDir, null, -1, false);
|
|
|
|
|
foreach (var item in recv)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("请输入回车");
|
|
|
|
|
Console.ReadLine();
|
|
|
|
|
Net.TCPSend(socket, @"D:\KSATProjects\2021-10-ASM\settings\SPI\Lanto_HTTP.INI", 512, 1);
|
|
|
|
|
Console.WriteLine("发送成功");
|
|
|
|
|
Net.TCPSend(socket, item, 512, 1);
|
|
|
|
|
Console.WriteLine($"{socket.RemoteEndPoint} {item} 发送成功");
|
|
|
|
|
Thread.Sleep(500);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 接收消息
|
|
|
|
|
/// 接收心跳和文件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="socketClientPara"></param>
|
|
|
|
|
private static void RecMsg(object socketClientPara)
|
|
|
|
|
private static void RecvMsg(object socketClientPara)
|
|
|
|
|
{
|
|
|
|
|
Socket socketClient = socketClientPara as Socket;
|
|
|
|
|
while (true)
|
|
|
|
|
while (true && socketClient.Connected)
|
|
|
|
|
{
|
|
|
|
|
//定义一个接受用的缓存区(100M字节数组)
|
|
|
|
|
//byte[] arrMsgRec = new byte[1024 * 1024 * 100];
|
|
|
|
|
//将接收到的数据存入arrMsgRec数组,并返回真正接受到的数据的长度
|
|
|
|
|
if (socketClient.Connected)
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
string fileSavePath = @"D:\ServerDir";//获得用户保存文件的路径
|
|
|
|
|
string[] recv = Net.RecvData(socketClient, new byte[25]);
|
|
|
|
|
switch (recv[0].TrimEnd('\0'))
|
|
|
|
|
{
|
|
|
|
|
//因为终端每次发送文件的最大缓冲区是512字节,所以每次接收也是定义为512字节
|
|
|
|
|
byte[] _buf = new byte[25];
|
|
|
|
|
byte[] buffer = new byte[512];
|
|
|
|
|
int size = 0;
|
|
|
|
|
long len = 0;
|
|
|
|
|
string fileSavePath = @"D:\ServerDir";//获得用户保存文件的路径
|
|
|
|
|
if (!Directory.Exists(fileSavePath))
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(fileSavePath);
|
|
|
|
|
}
|
|
|
|
|
//有文件发送才创建新文件
|
|
|
|
|
if (socketClient.Receive(_buf, 0, 25, SocketFlags.None) > 0)
|
|
|
|
|
{
|
|
|
|
|
//string recv = Encoding.Default.GetString(_buf);
|
|
|
|
|
//Console.WriteLine(socketClient.RemoteEndPoint + " 接收消息: " + DateTime.Now.ToString("yyyy:MM:dd HH:mm:ss:fff"));
|
|
|
|
|
string res = Encoding.Default.GetString(_buf);
|
|
|
|
|
string[] str = Regex.Split(res, "(&)");
|
|
|
|
|
if (str[0] == "1000")
|
|
|
|
|
case "1000":
|
|
|
|
|
string fileName = fileSavePath + "\\" + recv[2] + "\\" + recv[4].TrimEnd('\0');
|
|
|
|
|
string filePath = fileSavePath + "\\" + recv[2];//检查目录是否存在
|
|
|
|
|
if (!Directory.Exists(filePath))
|
|
|
|
|
{
|
|
|
|
|
string fileName = fileSavePath + "\\" + str[2] + "\\" + str[4].TrimEnd('\0');
|
|
|
|
|
//创建文件流,然后让文件流来根据路径创建一个文件
|
|
|
|
|
FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write);
|
|
|
|
|
//从终端不停的接受数据,然后写入文件里面,只到接受到的数据为0为止,则中断连接
|
|
|
|
|
|
|
|
|
|
DateTime oTimeBegin = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
while ((size = socketClient.Receive(buffer, 0, buffer.Length, SocketFlags.None)) > 0)
|
|
|
|
|
{
|
|
|
|
|
string flag = Encoding.Default.GetString(buffer, size - 1, 1);
|
|
|
|
|
if (flag.Equals("`"))
|
|
|
|
|
{
|
|
|
|
|
fs.Write(buffer, 0, size - 1);
|
|
|
|
|
len += size;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fs.Write(buffer, 0, size);
|
|
|
|
|
len += size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DateTime oTimeEnd = DateTime.Now;
|
|
|
|
|
TimeSpan oTime = oTimeEnd.Subtract(oTimeBegin);
|
|
|
|
|
fs.Flush();
|
|
|
|
|
fs.Close();
|
|
|
|
|
len -= 1;
|
|
|
|
|
Console.WriteLine("文件保存成功:" + fileName);
|
|
|
|
|
string store = (len / 1024.0) > 1.0 ? (len / 1024.0) + "kb" : len + "字节";
|
|
|
|
|
Console.WriteLine("接收文件用时:" + oTime.ToString() + ",文件大小:" + store);
|
|
|
|
|
//Console.WriteLine(socketClient.RemoteEndPoint + "断开连接");
|
|
|
|
|
//dict.Remove(socketClient.RemoteEndPoint.ToString());
|
|
|
|
|
//socketClient.Close();
|
|
|
|
|
Directory.CreateDirectory(filePath);
|
|
|
|
|
}
|
|
|
|
|
else if (str[0].TrimEnd('\0') == "1001")
|
|
|
|
|
{
|
|
|
|
|
Net.SendData(socketClient, Encoding.Default.GetBytes("1001"), 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine(socketClient.RemoteEndPoint + "下线了");
|
|
|
|
|
dict.Remove(socketClient.RemoteEndPoint.ToString());
|
|
|
|
|
break;
|
|
|
|
|
string recv2 = Net.RecvFile(socketClient, new byte[512], fileName);
|
|
|
|
|
Console.WriteLine($"{socketClient.RemoteEndPoint} {recv2}");
|
|
|
|
|
break;
|
|
|
|
|
case "1001":
|
|
|
|
|
Console.WriteLine($"{socketClient.RemoteEndPoint} 心跳回复");
|
|
|
|
|
Net.SendData(socketClient, Encoding.Default.GetBytes("1001"), 1);//服务端接收心跳后回复
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"{socketClient.RemoteEndPoint} 下线了");
|
|
|
|
|
dict.Remove(socketClient.RemoteEndPoint.ToString());
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -195,5 +140,54 @@ namespace TRI_TCP_Server
|
|
|
|
|
socketWatch.Close();
|
|
|
|
|
Console.WriteLine("服务器关闭监听");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region 获取指定目录下的所有文件
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取指定目录中的匹配项(文件或目录)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="dir">要搜索的目录</param>
|
|
|
|
|
/// <param name="regexPattern">项名模式(正则)。null表示忽略模式匹配,返回所有项</param>
|
|
|
|
|
/// <param name="depth">递归深度。负数表示不限,0表示仅顶级</param>
|
|
|
|
|
/// <param name="throwEx">是否抛异常</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static string[] GetFileSystemEntries(string dir, string regexPattern = null, int depth = 0, bool throwEx = false)
|
|
|
|
|
{
|
|
|
|
|
List<string> lst = new List<string>();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
foreach (string item in Directory.GetFileSystemEntries(dir))
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (regexPattern == null || Regex.IsMatch(Path.GetFileName(item), regexPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline))
|
|
|
|
|
{
|
|
|
|
|
if (!IsDir(item))
|
|
|
|
|
{
|
|
|
|
|
lst.Add(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//递归
|
|
|
|
|
if (depth != 0 && (File.GetAttributes(item) & FileAttributes.Directory) == FileAttributes.Directory)
|
|
|
|
|
{ lst.AddRange(GetFileSystemEntries(item, regexPattern, depth - 1, throwEx)); }
|
|
|
|
|
}
|
|
|
|
|
catch { if (throwEx) { throw; } }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch { if (throwEx) { throw; } }
|
|
|
|
|
|
|
|
|
|
return lst.ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 判断目标是文件夹还是目录(目录包括磁盘)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="filepath">路径</param>
|
|
|
|
|
/// <returns>返回true为一个文件夹,返回false为一个文件</returns>
|
|
|
|
|
public static bool IsDir(string filepath)
|
|
|
|
|
{
|
|
|
|
|
FileInfo fi = new FileInfo(filepath);
|
|
|
|
|
return (fi.Attributes & FileAttributes.Directory) != 0 ? true : false;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|