elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Evitar quedarse bloqueado al leer del puerto serie (C++ WinAPI)
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Evitar quedarse bloqueado al leer del puerto serie (C++ WinAPI)  (Leído 3,109 veces)
SARGE553413

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Evitar quedarse bloqueado al leer del puerto serie (C++ WinAPI)
« en: 7 Diciembre 2014, 22:35 pm »

Hola a todos.

Estoy haciendo una clase en C++ con funcionalidad para leer y escribir de distintas maneras en el puerto serie (con la Win32 API).
Como no tengo nada que use puerto serie, para hacer las pruebas estoy usando un emulador de puertos serie (com0com).

Estoy intentando implementar un método que lea todo lo que hay actualmente en el buffer del puerto serie, y si no hay nada, que no se quede bloqueado esperando.

He intentado hacerlo con OVERLAPPED pero, aparte de que no me ha funcionado, no me gusta la idea de tener que lanzar un hilo cada vez que quiero hacer esta opración.

Aquí el código que he escrito:
Código:
port = CreateFile(
string2LPCTSTR(this->portName), //\\\\.\\COM4"
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // default security attributes
OPEN_EXISTING,
0,
NULL
);
if (port == INVALID_HANDLE_VALUE)
throw SerialPortNativeIOException("Port value is INVALID_HANDLE_VALUE");

DCB portConfig;
if (GetCommState(port, &portConfig) == 0){
closeConnection();
this->port=INVALID_HANDLE_VALUE;
throw SerialPortNativeIOException("Error trying to get comm state");
}

setPortConfig(portConfig); //Esto simplemente asigna valores...

if(SetCommState(port, &portConfig)==0){
closeConnection();
this->port=INVALID_HANDLE_VALUE;
throw SerialPortNativeIOException("Error trying to set comm state");
}

setTimeoutConfig(); //Esto simplemente asigna valores...

if(SetCommTimeouts(port, &timeoutConfig)==0){
closeConnection();
this->port=INVALID_HANDLE_VALUE;
throw SerialPortNativeIOException("Error trying to set comm timeout config.");
}
this->connected=true;

...

std::string SerialPortNative::readExisting(){
ulong readBytes=0;
OVERLAPPED oR = {0};
oR.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(!ReadFile(this->port,this->buffer,READEXISTING_BUFFER_SIZE,&readBytes,&oR))
if(GetLastError() != ERROR_IO_PENDING)
throw SerialPortNativeIOException("Error reading from serial port");
return string(this->buffer,0,readBytes);
}

Al usar el método 'readExisting()' la lectura da error y no es ERROR_IO_PENDING, es el error con código 3 (ERROR_PATH_NOT_FOUND).

Ya he leído la documentación y ejemplos de msdn.microsoft y he googleado, pero no consigo hacerlo funcionar.

¿Qué puedo hacer? Gracias, saludos.


En línea

x64core


Desconectado Desconectado

Mensajes: 1.908


Ver Perfil
Re: Evitar quedarse bloqueado al leer del puerto serie (C++ WinAPI)
« Respuesta #1 en: 8 Diciembre 2014, 07:56 am »

Entonces cual es el problema ReadFile retornando ERROR_PATH_NOT_FOUND?
Si vas a solicitar de forma asincronica entonces necesitas establecer la bandera FILE_FLAG_OVERLAPPED en CreateFile, solicitando acceso exclusivo del dispositivo no es bueno, pero bueno ya sabras.

Si el hilo se queda bloqueado es porque la solicitud esta esperando que sea completada, podes crear un worker thread ( crearlo al construir la clase por ejemplo, asi no es necesario crear un hilo cada vez que se quiere leer ). Si la solicitud es asincronica, despues de llamar a ReadFile tendras que esperar por el evento usando WaitForSIngleObject.


En línea

SARGE553413

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Re: Evitar quedarse bloqueado al leer del puerto serie (C++ WinAPI)
« Respuesta #2 en: 8 Diciembre 2014, 14:36 pm »

Hola, gracias por la respuesta.

No me refería a que el hilo se quedase bloqueado, quiero decir que hacer ReadFile sin OVERLAPPED si se queda bloqueado, lo que quiero es tener una función que haga ReadFile a lo que haya en el buffer, y si no hay nada, que no se quede bloqueado.

Para ello creo que la manera de hacerlo es con OVERLAPPED, y al hacer ReadFile internamente se lanza un hilo, si yo lo he entendido bien.

Mi problema entonces es que no uso bien el OVERLAPPED porque la función ReadFile me devuelve un error que no es ERROR_IO_PENDING (que es lo que debería devolverme si no hay nada en el buffer).

He seguido intentándolo, pero aún no ha habido suerte.

Saludos.

EDITO:
He cambiado el CreateFile para ponerlo en lectura compartida y FILE_FLAG_OVERLAPPED y algunos otros errores que tenía, ahora el readExisting()
"parece" que funciona bien, porque al hacerlo me devuelve una cadena vacía.
El problema es que con el emulador que uso, al hacer write sobre COM3 (que está conectado a COM4), si no tengo abierto el hyperterminal no escribe nada en el buffer, no se por qué. El caso es que no puedo probarlo del todo pero creo que ya va bien, gracias por la respuesta. Si consigo comprobar que todo funciona subo el código para el que lo quiera ver.

Saludos.


EDITO 2:
Resulta que si hacemos el CreateFile con FILE_FLAG_OVERLAPPED ya no se pueden hacer lecturas síncronas. Tiene que ser lo uno o lo otro. La única solución que veo entonces (para hacer una clase que tenga métodos síncronos y asíncronos) es pasar del overlapped y crearme yo mis propios hilos. Si hay alguna manera mejor de hacerlo, agradeceré que me lo expliquen. No tengo claro si será mejor idea andar con hilos o, cada vez que quiera hacer el readExisting(), cambiar el readtimeout del puerto a 0.

Saludos.
« Última modificación: 8 Diciembre 2014, 15:32 pm por SARGE553413 » En línea

x64core


Desconectado Desconectado

Mensajes: 1.908


Ver Perfil
Re: Evitar quedarse bloqueado al leer del puerto serie (C++ WinAPI)
« Respuesta #3 en: 8 Diciembre 2014, 18:55 pm »

Hola, gracias por la respuesta.

No me refería a que el hilo se quedase bloqueado, quiero decir que hacer ReadFile sin OVERLAPPED si se queda bloqueado, lo que quiero es tener una función que haga ReadFile a lo que haya en el buffer, y si no hay nada, que no se quede bloqueado.

Para ello creo que la manera de hacerlo es con OVERLAPPED, y al hacer ReadFile internamente se lanza un hilo, si yo lo he entendido bien.

Mi problema entonces es que no uso bien el OVERLAPPED porque la función ReadFile me devuelve un error que no es ERROR_IO_PENDING (que es lo que debería devolverme si no hay nada en el buffer).

He seguido intentándolo, pero aún no ha habido suerte.

Saludos.
Me referia a eso mismo, Windows pone en modo de espera el hilo que es usado para solicitar peticiones sincronicas, queda esperando hasta que la solicitud es completada.

EDITO:
He cambiado el CreateFile para ponerlo en lectura compartida y FILE_FLAG_OVERLAPPED y algunos otros errores que tenía, ahora el readExisting()
"parece" que funciona bien, porque al hacerlo me devuelve una cadena vacía.
El problema es que con el emulador que uso, al hacer write sobre COM3 (que está conectado a COM4), si no tengo abierto el hyperterminal no escribe nada en el buffer, no se por qué. El caso es que no puedo probarlo del todo pero creo que ya va bien, gracias por la respuesta. Si consigo comprobar que todo funciona subo el código para el que lo quiera ver.

Saludos.
Entonces ¿cómo el programador sabria si fue enviado con exito?

EDITO 2:
Resulta que si hacemos el CreateFile con FILE_FLAG_OVERLAPPED ya no se pueden hacer lecturas síncronas. Tiene que ser lo uno o lo otro. La única solución que veo entonces (para hacer una clase que tenga métodos síncronos y asíncronos) es pasar del overlapped y crearme yo mis propios hilos. Si hay alguna manera mejor de hacerlo, agradeceré que me lo expliquen. No tengo claro si será mejor idea andar con hilos o, cada vez que quiera hacer el readExisting(), cambiar el readtimeout del puerto a 0.

Saludos.
Usando el mismo handle para para solicitudes sincronicas y asincronicas no es posible, sino ¿cómo haria Windows para saber cuando el programador necesita una petición sincronica o asincronica? al crear el objeto de archivo este contiene unas banderas donde guarda la información. Podes abrir más de un handle, una para peticiónes sincronicas y otro para asincronicas o podes usar ReOpenFile para cambiar los attributos del handle mismo.

-

Toma en cuenta que si las peticiones son asincronicas no habrá espera asi que el contenido del buffer es indefinido, para saber si la solicitud fue completada usa WaitForSingleObject con el mismo evento pasado a las funciones.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Librerias para leer el puerto Serie desde PHP
PHP
Graphixx 2 7,036 Último mensaje 23 Agosto 2011, 13:57 pm
por [u]nsigned
Problema leer/escribir puerto serie (C++ WINAPI)
Programación C/C++
SARGE553413 9 5,665 Último mensaje 20 Agosto 2014, 11:36 am
por Eternal Idol
Leer puerto serie y mostrar texto en cuadro de texto
Java
Meta 0 3,391 Último mensaje 6 Marzo 2015, 21:33 pm
por Meta
[Python] leer puerto serie desde PyQt5 y arduino y mostrase interfaz grafica
Scripting
jenju302 4 5,985 Último mensaje 5 Noviembre 2016, 04:03 am
por Once
Leer puro byte del puerto serie
.NET (C#, VB.NET, ASP)
Meta 0 2,900 Último mensaje 8 Noviembre 2023, 21:40 pm
por Meta
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines