Поделиться через


Отключение сокета от назначения

Когда приложение Winsock Kernel (WSK) завершило отправку и получение данных по установленному подключению сокета, оно может отключить сокет, ориентированный на подключение, от удаленного транспортного адреса, к которому он подключен. Приложение WSK отключает сокет от удаленного адреса транспорта путем вызова функции WskDisconnect. Приложение WSK может выполнять либо аварийное отключение, либо плавное отключение сокета. Дополнительные сведения о разнице между прерыванием и плавным отключением см. в разделе WskDisconnect.

В следующем примере кода показано, как приложение WSK может корректно отключить сокет, ориентированный на подключение, от удаленного адреса транспорта.

// Prototype for the disconnect IoCompletion routine
NTSTATUS
  DisconnectComplete(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp,
    PVOID Context
    );

// Function to disconnect a socket from a remote transport address
NTSTATUS
  DisconnectSocket(
    PWSK_SOCKET Socket
    )
{
  PWSK_PROVIDER_CONNECTION_DISPATCH Dispatch;
  PIRP Irp;
  NTSTATUS Status;
 
  // Get pointer to the socket's provider dispatch structure
  Dispatch =
    (PWSK_PROVIDER_CONNECTION_DISPATCH)(Socket->Dispatch);

  // Allocate an IRP
  Irp =
    IoAllocateIrp(
      1,
      FALSE
      );

  // Check result
  if (!Irp)
  {
    // Return error
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  // Set the completion routine for the IRP
  IoSetCompletionRoutine(
    Irp,
    DisconnectComplete,
    Socket,  // Use the socket object for the context
    TRUE,
    TRUE,
    TRUE
    );

  // Initiate the disconnect operation on the socket
  Status =
    Dispatch->WskDisconnect(
      Socket,
      NULL,  // No final data to be transmitted
      0,     // No flags (graceful disconnect)
      Irp
      );

  // Return the status of the call to WskDisconnect()
  return Status;
}

// Disconnect IoCompletion routine
NTSTATUS
  DisconnectComplete(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp,
    PVOID Context
    )
{
  UNREFERENCED_PARAMETER(DeviceObject);

  PWSK_SOCKET Socket;

  // Check the result of the disconnect operation
  if (Irp->IoStatus.Status == STATUS_SUCCESS)
  {
    // Get the socket object from the context
    Socket = (PWSK_SOCKET)Context;

    // Perform the next operation on the socket
    ...
  }

  // Error status
  else
  {
    // Handle error
    ...
  }

  // Free the IRP
  IoFreeIrp(Irp);

  // Always return STATUS_MORE_PROCESSING_REQUIRED to
  // terminate the completion processing of the IRP.
  return STATUS_MORE_PROCESSING_REQUIRED;
}

Если приложение WSK выполняет корректное отключение сокета, оно может отправить завершающий буфер данных на удаленный транспортный адрес до отключения сокета, передав указатель на структуру WSK_BUF в функцию WskDisconnect.

Если приложение WSK закрывает cоединительный сокет, не отключив его принудительно от удаленного транспортного адреса, к которому он подключен, подсистема WSK автоматически выполняет принудительное отключение сокета перед его закрытием. Дополнительные сведения о закрытии сокета см. в разделе Закрытие сокета.