/// <summary> /// 连接至服务器。 /// </summary> /// <param name="endpoint">服务器终结点。</param> public void Connect(IPEndPoint endpoint) { //判断是否已连接 if (IsConnected) { throw new InvalidOperationException("已连接至服务器。"); } if (endpoint == null) { throw new ArgumentNullException("endpoint"); } //锁定自己,避免多线程同时操作 lock (this) { SocketAsyncState state = new SocketAsyncState(); //Socket异步连接 Socket.BeginConnect(endpoint, EndConnect, state).AsyncWaitHandle.WaitOne(); //等待异步全部处理完成 while (!state.Completed) { Thread.Sleep(1); } } }
private static Exception ThrowException(SocketAsyncState state) { var statusName = Enum.GetName(typeof(ResponseStatus), state.Status); switch (state.Status) { case ResponseStatus.KeyNotFound: return(new KeyNotFoundException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.KeyExists: return(new KeyExistsException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.ValueTooLarge: return(new ValueTooLargeException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.InvalidArguments: return(new InvalidArgumentException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.TemporaryFailure: case ResponseStatus.OutOfMemory: case ResponseStatus.Busy: return(new TempFailException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.OperationTimeout: return(new TimeoutException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.Locked: return(new KeyLockedException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.DocumentMutationLost: case ResponseStatus.DocumentMutationDetected: case ResponseStatus.NoReplicasFound: case ResponseStatus.DurabilityInvalidLevel: case ResponseStatus.DurabilityImpossible: case ResponseStatus.SyncWriteInProgress: case ResponseStatus.SyncWriteAmbiguous: return(new DurabilityException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.Eaccess: case ResponseStatus.AuthenticationError: return(new AuthenticationException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); //internal errors handled by the app? case ResponseStatus.Rollback: case ResponseStatus.VBucketBelongsToAnotherServer: case ResponseStatus.AuthenticationContinue: case ResponseStatus.AuthStale: case ResponseStatus.InternalError: case ResponseStatus.UnknownCommand: case ResponseStatus.BucketNotConnected: case ResponseStatus.UnknownError: case ResponseStatus.NotInitialized: case ResponseStatus.NotSupported: case ResponseStatus.SubdocXattrUnknownVattr: case ResponseStatus.SubDocMultiPathFailure: case ResponseStatus.SubDocXattrInvalidFlagCombo: case ResponseStatus.SubDocXattrInvalidKeyCombo: case ResponseStatus.SubdocXattrCantModifyVattr: case ResponseStatus.SubdocMultiPathFailureDeleted: case ResponseStatus.SubdocInvalidXattrOrder: return(new InternalErrorException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.InvalidRange: case ResponseStatus.ItemNotStored: case ResponseStatus.IncrDecrOnNonNumericValue: return(new KeyValueException //hmm? { Status = state.Status, ErrorMap = state.ErrorMap }); //sub doc errors case ResponseStatus.SubDocPathNotFound: return(new PathNotFoundException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.SubDocPathMismatch: return(new PathMismatchException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.SubDocPathInvalid: return(new PathInvalidException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.SubDocPathTooBig: return(new PathTooBigException(statusName, new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap })); case ResponseStatus.SubDocDocTooDeep: case ResponseStatus.SubDocCannotInsert: case ResponseStatus.SubDocDocNotJson: case ResponseStatus.SubDocNumRange: case ResponseStatus.SubDocDeltaRange: case ResponseStatus.SubDocPathExists: case ResponseStatus.SubDocValueTooDeep: case ResponseStatus.SubDocInvalidCombo: case ResponseStatus.SubdocXattrUnknownMacro: return(new KeyValueException { Status = state.Status, ErrorMap = state.ErrorMap }); //remove these ones case ResponseStatus.Failure: case ResponseStatus.ClientFailure: break; case ResponseStatus.NodeUnavailable: break; case ResponseStatus.TransportFailure: return(state.Exception); default: return(new ArgumentOutOfRangeException()); } return(new Exception("oh me oh mai...")); }
public async Task SendAsync(ReadOnlyMemory <byte> request, Func <SocketAsyncState, Task> callback, ErrorMap errorMap) { ExceptionDispatchInfo capturedException = null; SocketAsyncState state = null; try { var opaque = ByteConverter.ToUInt32(request.Span.Slice(HeaderOffsets.Opaque)); state = new SocketAsyncState { Opaque = opaque, EndPoint = (IPEndPoint)EndPoint, ConnectionId = ConnectionId, LocalEndpoint = LocalEndPoint.ToString() }; if (!MemoryMarshal.TryGetArray <byte>(request, out var arraySegment)) { // Fallback in case we can't use the more efficient TryGetArray method arraySegment = new ArraySegment <byte>(request.ToArray()); } // write data to stream await _sslStream.WriteAsync(arraySegment.Array, 0, request.Length).ConfigureAwait(false); // wait for response var received = await _sslStream.ReadAsync(_receiveBuffer, 0, _receiveBuffer.Length).ConfigureAwait(false); var responseSize = ByteConverter.ToInt32(_receiveBuffer.AsSpan(HeaderOffsets.BodyLength)) + HeaderOffsets.HeaderLength; // create memory slice and copy first segment var response = MemoryPool <byte> .Shared.RentAndSlice(responseSize); _receiveBuffer.AsMemory(0, received).CopyTo(response.Memory); // append any further segments as required while (received < responseSize) { var segmentLength = await _sslStream.ReadAsync(_receiveBuffer, 0, _receiveBuffer.Length).ConfigureAwait(false); _receiveBuffer.AsMemory(0, segmentLength).CopyTo(response.Memory); received += segmentLength; } // write response to state and complete callback state.SetData(response); await callback(state).ConfigureAwait(false); } catch (Exception e) { IsDead = true; capturedException = ExceptionDispatchInfo.Capture(e); } if (capturedException != null) { var sourceException = capturedException.SourceException; if (state == null) { await callback(new SocketAsyncState { Exception = capturedException.SourceException, Status = (sourceException is SocketException) ? ResponseStatus.TransportFailure : ResponseStatus.ClientFailure }).ConfigureAwait(false); } else { state.Exception = sourceException; await state.Completed(state).ConfigureAwait(false); Log.LogDebug(sourceException, ""); } } }