c++ - Bloqueo de bloqueo de ReadFile()-Canalizaciones con nombre(API de Windows)
winapi named-pipes (6)
Para simplificar, esta es una situación en la que un SERVER de NamedPipe está esperando que un CLIENTE de NamedPipe escriba en la tubería (usando WriteFile ())
La API de Windows que está bloqueando es ReadFile ()
El servidor ha creado el conducto síncrono (sin E / S superpuestas) con el bloqueo habilitado
El cliente se ha conectado, y ahora el servidor está esperando algunos datos.
En el flujo normal de cosas, el cliente envía algunos datos y el servidor los procesa y luego regresa a ReadFile () para esperar el siguiente fragmento de datos.
Mientras tanto, se produce un evento (por ejemplo, la entrada del usuario) y NamedPipe SERVER debe ejecutar ahora otro código, que no puede hacer mientras ReadFile () está bloqueando.
En este punto, debo mencionar que NamedPipe Client no es mi aplicación, por lo que no tengo control sobre ella. No puedo enviar unos bytes para desbloquear el servidor. Simplemente se sentará allí y no enviará datos. Como no tengo control de la implementación del Cliente, no puedo cambiar nada en ese extremo.
Una solución sería crear un hilo separado en el que se realicen todas las operaciones de ReadFile (). De esa forma, cuando ocurre el evento, puedo procesar el código. El problema con eso, es que el evento también requiere un hilo separado, por lo que ahora tengo dos hilos adicionales para cada instancia de este servidor. Como esto necesita ser escalable, esto no es deseable.
De otro hilo que he intentado llamar
DisconnectNamedPipe()
y
CloseHandle()
ambos no regresarán (hasta que el cliente escriba a la tubería).
No puedo conectarme al mismo conducto y escribir algunos bytes porque:
"Todas las instancias de un conducto con nombre comparten el mismo nombre de canalización, pero cada instancia tiene sus propios búferes y controladores, y proporciona un conducto separado para la comunicación cliente / servidor".
http://msdn.microsoft.com/en-us/library/aa365590.aspx
Necesito una manera de fingir, así que la pregunta de $ 64k es:
¿Cómo puedo romper el bloqueo de ReadFile ()?
El problema con eso, es que el evento también requiere un hilo separado, por lo que ahora tengo dos hilos adicionales para cada instancia de este servidor. Como esto necesita ser escalable, esto no es deseable.
Nunca en mi carrera he encontrado que "más hilos" == "menos escalable". ¿Cuántas de estas instancias de "servidor" tiene?
Normalmente, una operación debe realizarse en una secuencia separada si esa operación se va a bloquear y el sistema debe responder mientras la operación está bloqueada.
Eche un vistazo en CancelSynchronousIo
Marcas pendientes de las operaciones de E / S síncronas emitidas por el hilo especificado como canceladas.
Y CancelIo / CancelIoEx:
Para cancelar todas las operaciones de E / S asíncronas pendientes, use:
CancelIo: esta función solo cancela las operaciones emitidas por la secuencia de llamada para el manejador de archivo especificado.
CancelIoEx: esta función cancela todas las operaciones emitidas por los hilos para el manejador de archivo especificado.
Las operaciones de E / S asincrónicas no tienen que bloquear ningún subproceso si utilizan puertos de finalización de E / S. Ver: http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx
Lo que ocurre es que el conducto de salida del servidor se deja abierto esperando la conexión mientras su cliente intenta conectarse al conducto entrante del servidor (que ya no existe) ... Lo que necesita hacer es eliminar su tubería de salida para poder buclear de vuelta a su entrante. Puede limpiar el lado del cliente leyendo el archivo (recuerde hacer un bucle en el establecimiento de conexión porque hay un "apretón de manos" allí, y nunca funcionará la primera vez)
Micro,
No puede cancelar ReadFile sincrónico. Pero puede cambiar a operaciones asincrónicas (superpuestas). Al hacer esto, puede implementar una arquitectura bastante escalable.
Algoritmo posible (solo una idea):
- Para cada nuevo cliente, llame a ReadFile
- WaitForMultipleObjects donde los mangos están superpuestos.hEvent + tus eventos personalizados
- Itera sobre los eventos señalados, y programarlos para su ejecución por hilos desde un grupo de hilos.
De esta forma, puede tener solo pocos hilos para recibir conexiones y leer datos, mientras que el procesamiento de datos real puede hacerlo el grupo de hilos.
Pruebe esto antes de ReadFile:
BOOL WINAPI PeekNamedPipe(
__in HANDLE hNamedPipe,
__out_opt LPVOID lpBuffer,
__in DWORD nBufferSize,
__out_opt LPDWORD lpBytesRead,
__out_opt LPDWORD lpTotalBytesAvail,
__out_opt LPDWORD lpBytesLeftThisMessage
);
if(TotalBytesAvail > 0)
ReadFile(....);
-AV-