La diferencia entre sockets bloqueantes y no bloqueantes en la programación de redes Linux
La diferencia entre sockets bloqueantes y sockets no bloqueantes:
1. Operación de lectura
Para sockets bloqueados, cuando no hay datos en el búfer de recepción del socket. , La llamada de lectura se bloqueará hasta que lleguen los datos antes de regresar. Cuando la cantidad de datos en el búfer del socket es menor que la cantidad de datos que se espera leer, se devuelve el número real de bytes leídos. Cuando los datos en el búfer de recepción del sockt son mayores que la cantidad de bytes que se espera leer, se lee la cantidad esperada de bytes que se leerán y se devuelve la longitud de lectura real.
Para sockets sin bloqueo, si hay datos en el búfer de recepción del socket, la llamada de lectura regresará inmediatamente. Cuando hay datos en el búfer de recepción, es lo mismo que cuando hay datos en el socket de bloqueo. Si no hay datos en el búfer de recepción, el número de error devuelto es EWOULDBLOCK, lo que indica que la operación debería haberse bloqueado, pero. Debido a que el socket es un socket que no bloquea, regresa inmediatamente. Si encuentra tal situación, puede intentar leerlo la próxima vez. Si el valor de retorno es negativo, indica un error de lectura.
Por lo tanto, las llamadas rea sin bloqueo generalmente se escriben así:
if ((nread = read(sock_fd, buffer, len)) lt; 0)
{
if (errno == EWOULDBLOCK)
{
return 0; //Indica que no se han leído datos
}else return -1; // Indica error de lectura
}else return nread; leer la longitud de los datos
2. , el principio es De manera similar, un socket sin bloqueo devolverá directamente el número de error EWOULDBLOCK cuando no hay espacio en el búfer de envío, lo que indica que no hay espacio para escribir datos. Si el número de error es otro valor, indica que el. El envío falló. Si hay suficiente espacio en el búfer de envío o no hay suficiente espacio para copiar todos los datos a enviar, se copiarán los primeros N datos que se puedan acomodar y se devolverá el número real de bytes copiados.
Para bloquear Socket, si el búfer de envío no tiene espacio o no tiene espacio suficiente, la operación de escritura se bloqueará directamente. Si hay suficiente espacio, todos los datos se copiarán al búfer de envío y luego se devolverán.
El método de escritura general para operaciones de escritura sin bloqueo es:
int write_pos = 0;
int nLeft = nLen;
mientras (nLeft gt ; 0)
{
int nWrite = 0;
if ((nWrite = write(sock_fd, data write_pos, nLeft)) lt; = 0)
{
if (errno == EWOULDBLOCK)
{
nWrite = 0
}else return -1; // Indica error de escritura
}
nLeft -= nWrite
write_pos = nWrite; } p>
return nLen;
3. Establecer conexión
En modo de bloqueo, conectar primero envía una solicitud SYN al servidor cuando el cliente recibe la confirmación SYN. devuelto por el servidor, luego connect regresa. De lo contrario, siempre se bloqueará.
En el modo sin bloqueo, connect habilitará el protocolo de enlace de tres vías del protocolo TCP, pero la función de conexión no espera. para que la conexión se establezca antes de regresar, pero regresa inmediatamente. El código de error devuelto es EINPROGRESS, lo que indica que hay algún proceso en progreso.
Recepción de conexión
Para el socket de escucha de bloqueo, aceptar no tiene una buena conexión establecida en la conexión. cola. Se bloqueará hasta que haya una conexión disponible antes de regresar.
El socket de escucha sin bloqueo regresa inmediatamente ya sea que haya una conexión o no. Cuando no hay conexión, el código de error devuelto es EWOULDBLOCK, lo que indica que debería haberse bloqueado.
Método de configuración sin bloqueo
Método 1: fcntl
int flag;
if (flag = fcntl(fd, F_GETFL, 0) lt; 0) perror("obtener bandera");
bandera |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, bandera) lt; 0)
error("set flag");
Método 2: ioctl
int b_on = 1;
ioctl (fd, FIONBIO, amp; b_on);