/// <summary> /// 发送一个数据库操作请求。如果发送成功返回true,否则返回false /// </summary> /// <param name="userModel">用户对象</param> /// <param name="operation">操作类型</param> /// <param name="parameter">操作参数</param> public bool SendDatabaseRequest(User user, string operation, string parameter) { if (ClientState) { byte[] buffer = BytesConvert.ObjectToBytes(new Transmit() { SourceID = ClientID, TargetID = ClientID, DataType = DataType.Request, Parameter = $"Database;{operation},{parameter}", Object = user }); SocketAsyncEventArgs args = new SocketAsyncEventArgs(); try { args.SetBuffer(buffer, 0, buffer.Length); clientSocket.SendAsync(args); return(true); } catch (Exception exception) { ClientError?.Invoke(this, new ClientErrorEventArgs(exception, "在发送请求时发生错误")); } finally { args.Dispose(); } } return(false); }
/// <summary> /// 异步的发送文本消息。如果发送成功返回true,否则返回false /// </summary> /// <param name="targetUserID">目标用户ID</param> /// <param name="message">文本消息</param> public async Task <bool> SendTextAsync(string targetUserID, string message) { if (ClientState && targetUserID != null && message != null) { return(await Task.Run <bool>(() => { byte[] buffer = BytesConvert.ObjectToBytes(new Transmit() { SourceID = ClientID, TargetID = targetUserID, DataType = DataType.Text, Parameter = message }); try { clientSocket.Send(buffer, buffer.Length, SocketFlags.None); return true; } catch (Exception exception) { ClientError?.Invoke(this, new ClientErrorEventArgs(exception, "在发送文本消息时发生错误")); return false; } })); } return(false); }
/// <summary> /// 异步的发送图片。如果发送成功返回true,否则返回false /// </summary> /// <param name="targetUserID">目标ID</param> /// <param name="imagePath">图片路径</param> public async Task <bool> SendImageAsync(string targetUserID, string imagePath) { if (ClientState && targetUserID != null && imagePath != null) { return(await Task.Run <bool>(() => { FileStream fileStream = null; //文件流 byte[] dataBuffer = new byte[1024 * 1024]; //数据缓冲区 try { fileStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read); if (fileStream.Length == 0) { return false; } byte[] buffer = BytesConvert.ObjectToBytes(new Transmit() { SourceID = ClientID, TargetID = targetUserID, DataType = DataType.Image, Parameter = $"{Path.GetFileName(imagePath)};{fileStream.Length}" }); clientSocket.Send(buffer, buffer.Length, SocketFlags.None); Thread.Sleep(100); while (true) { int readBytes = fileStream.Read(dataBuffer, 0, dataBuffer.Length); if (readBytes <= 0) { break; } clientSocket.Send(dataBuffer, readBytes, SocketFlags.None); Thread.Sleep(10); } } catch (Exception exception) { ClientError?.Invoke(this, new ClientErrorEventArgs(exception, "在发送图片时发生错误")); return false; } finally { fileStream?.Close(); fileStream?.Dispose(); fileStream = null; } return true; })); } return(false); }
/// <summary> /// 接收数据 /// </summary> /// <param name="socket">客户端Socket对象</param> private void ReceiveMessage(Socket socket) { bool isMain = true; //是否为主端口 string clientID = string.Empty; //客户端ID IPEndPoint clientIPEndPoint = (IPEndPoint)socket.RemoteEndPoint; //客户端网络终结点 bool isFirstConnection = true; //是否为首次连接 byte[] dataBuffer = new byte[1024 * 1024]; //缓冲区 bool isFirstReceive = true; //是否为首次接收数据 Transmit transmit = null; //传输对象 double dataSize = 0.0; //数据总大小 double receiveBytes = 0.0; //已接收的字节数 int targetPort = -1; //发送目标端口 while (true) { int readBytes = 0; if (socket.Poll(-1, SelectMode.SelectRead) == true) { if (!ServerState) { break; } try { readBytes = socket.Receive(dataBuffer, dataBuffer.Length, SocketFlags.None); if (readBytes == 0) { if (isMain) { CloseClient(clientID); break; } CloseClientPort(clientID, clientIPEndPoint.Port); break; } } catch (Exception exception) { if (isMain) { CloseClient(clientID, false, exception); break; } CloseClientPort(clientID, clientIPEndPoint.Port, false, exception); break; } } //首次连接 if (isFirstConnection) { isFirstConnection = false; clientID = Encoding.UTF8.GetString(dataBuffer, 0, readBytes); if (clientCollection.AddClient(clientID, clientIPEndPoint, socket)) { ServerMessage?.Invoke(this, new ServerNotifyEventArgs($"客户端 {clientID}({clientIPEndPoint}) 已连接")); } else { if (!clientCollection.AddPort(clientID, clientIPEndPoint.Port, socket)) { break; } isMain = false; ServerMessage?.Invoke(this, new ServerNotifyEventArgs($"客户端 {clientID} 的 {clientIPEndPoint.Port} 端口已连接")); } socket.Send(new byte[] { 1 }); continue; } //首次接收数据 if (isFirstReceive) { isFirstReceive = false; transmit = BytesConvert.BytesToObject(dataBuffer, readBytes, "MiniSocket.Transmitting") as Transmit; if (transmit?.Parameter == null) { ResetParameter(ref isFirstReceive, ref transmit, ref dataSize, ref receiveBytes); continue; } if (isMain) { string[] parameters = transmit.Parameter.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); switch (transmit.DataType) { case DataType.Text: if (!Forward(transmit, dataBuffer, readBytes)) { return; } break; case DataType.Image: if (parameters.Length == 2) { if (double.TryParse(parameters[1], out dataSize)) { if (!Forward(transmit, dataBuffer, readBytes)) { return; } continue; } } break; case DataType.Request: if (transmit.Parameter.StartsWith("Database")) { if (parameters.Length == 2) { var result = DatabaseRequest?.Invoke(this, new DatabaseEventArgs(parameters[1], transmit.Object))?.Result; if (result != null) { transmit.Parameter = "Client;RequestResult"; transmit.Object = result; byte[] buffer = BytesConvert.ObjectToBytes(transmit); if (!Forward(transmit, buffer, buffer.Length)) { return; } } } } break; } ResetParameter(ref isFirstReceive, ref transmit, ref dataSize, ref receiveBytes); continue; } if (transmit.DataType == DataType.File) { string[] parameters = transmit.Parameter.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); if (parameters.Length == 2) { if (double.TryParse(parameters[1], out dataSize)) { Transmit requestTransmit = new Transmit() { SourceID = transmit.SourceID, TargetID = transmit.TargetID, DataType = DataType.Request, Parameter = "Client;AddSocket" }; byte[] buffer = BytesConvert.ObjectToBytes(requestTransmit); if (!Forward(requestTransmit, buffer, buffer.Length)) { return; } Thread.Sleep(3000); List <Socket> sockets = clientCollection.GetClientSockets(transmit.TargetID); targetPort = ((IPEndPoint)sockets[sockets.Count - 1].RemoteEndPoint).Port; if (!Forward(transmit, dataBuffer, readBytes, targetPort)) { return; } continue; } } } CloseClientPort(clientID, clientIPEndPoint.Port); return; } receiveBytes += readBytes; //已接收到的数据累加 //判断已接收到的数据是否有效 if (receiveBytes > 0 && receiveBytes <= dataSize) { if (!Forward(transmit, dataBuffer, readBytes, targetPort)) { break; } } //判断是否接收完成或数据是否有误 if (receiveBytes == dataSize || (receiveBytes <= 0 || receiveBytes > dataSize)) { if (isMain) { ResetParameter(ref isFirstReceive, ref transmit, ref dataSize, ref receiveBytes); continue; } CloseClientPort(clientID, clientIPEndPoint.Port); break; } } }
/// <summary> /// 异步的发送文件。如果发送成功返回true,否则返回false /// </summary> /// <param name="targetUserID">目标ID</param> /// <param name="filePath">文件路径</param> public async Task <bool> SendFileAsync(string targetUserID, string filePath) { if (ClientState && targetUserID != null && filePath != null) { return(await Task.Run <bool>(async() => { FileStream fileStream = null; //文件流 byte[] dataBuffer = new byte[1024 * 1024]; //数据缓冲区 try { fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); if (fileStream.Length == 0) { return false; } byte[] buffer = BytesConvert.ObjectToBytes(new Transmit() { SourceID = ClientID, TargetID = targetUserID, DataType = DataType.File, Parameter = $"{Path.GetFileName(filePath)};{fileStream.Length}" }); SocketResult socketResult = await socketManager.CreateConnectionAsync(); switch (socketResult.State) { case ConnectionState.Success: socketResult.Socket.Send(buffer, buffer.Length, SocketFlags.None); break; case ConnectionState.Failed: throw new ArgumentException("服务器拒绝连接"); case ConnectionState.Timeout: throw new ArgumentException("服务器连接超时"); case ConnectionState.Error: throw socketResult.Exception; } Thread.Sleep(5000); while (true) { int readBytes = fileStream.Read(dataBuffer, 0, dataBuffer.Length); if (readBytes <= 0) { break; } socketResult.Socket.Send(dataBuffer, readBytes, SocketFlags.None); Thread.Sleep(10); } } catch (Exception exception) { ClientError?.Invoke(this, new ClientErrorEventArgs(exception, "在发送文件时发生错误")); return false; } finally { fileStream?.Close(); fileStream?.Dispose(); fileStream = null; } return true; })); } return(false); }