File I/O mode comparison
1. Blocking file I/O
The process starts from the calling function until the time it is returned is blocked.
2. Non-blocking file I/O
If no data is currently operational, the current process is not blocked and an error message is returned immediately. Need to try again and again.
3. Multiplexing I/O
The blocking mode is still waiting, but you can wait for multiple file descriptors at the same time.
4. Signal-driven I/O
Asynchronous way, wait until the data is ready to notify the processing process, do not need to repeat the query, high efficiency.
I/O blocking and non-blocking operations
blocking mode : By default Read/write and flag set to 0 recv/send
non-blocking mode : If there is no data, return immediately 1 indicates failure and modify the system global variable errno value to Eagain, indicating that the data is not ready.
This can be achieved by setting the RECV msg_dontwait flag. If setting the file descriptor property of the socket is non-blocking, all subsequent operations against the file descriptor will be non-blocking.
Example:
Server-side: Receive non-blocking, send blocking. Multiple lines can be sent consecutively. If the other party sends a lot of data, it will be received once.
Client: Both send and receive are blocked. In this example, the receiving end must be received one, send a line so alternating. If the server sends more than one, it will be received separately.
Strange: In this example, the receiving end also binds to its own address, but the previous example is not bound. Both have achieved communication, for what?
Server code:
#include <sys/types.h>#include<sys/socket.h>#include<stdio.h>#include<string.h>#include<netinet/inch.h>#include<arpa/inet.h>#include<unistd.h>#include<stdlib.h>#include<errno.h>#defineBUFSIZE 128intMainintargcChar*argv[]) { intSERVER_SOCKFD, CLIENT_SOCKFD; intServer_len, Client_len; structsockaddr_in server_address; structsockaddr_in client_address; intIbyte; CharChar_send[bufsize]; //creating a Socket object BlockSERVER_SOCKFD = socket (af_inet, Sock_stream,0); Server_address.sin_family=af_inet; //extract IP address from argv[1] if(Inet_aton (argv[1],(structin_addr*) &server_address.sin_addr.s_addr) = =0) {perror (argv[1]); Exit (Exit_failure); } server_address.sin_port= Htons (7838);//use a specific portServer_len =sizeof(server_address); //Binding IP InformationBind (SERVER_SOCKFD, (structSOCKADDR *) &server_address, Server_len); //Listening NetworkListen (SERVER_SOCKFD,5); printf ("server waiting for connect\n"); Client_len=sizeof(client_address); //Waiting for connectionCLIENT_SOCKFD = Accept (SERVER_SOCKFD, (structSOCKADDR *) &client_address, (socklen_t *) &Client_len); for(i =0; I <5; i++) {memset (Char_send,' /', BUFSIZE); printf ("input message to send:"); Fgets (Char_send, BUFSIZE, stdin); //block in terminal, receive user input data//Send if((byte= Send (CLIENT_SOCKFD, Char_send, strlen (Char_send),0)) == -1) {perror ("Send"); Exit (Exit_failure); } memset (Char_send,' /', BUFSIZE); //non-blocking receive byte=recv (CLIENT_SOCKFD, Char_send, BUFSIZE, msg_dontwait); if(byte>0) {printf ("Get%d message:%s",byte, Char_send); byte=0; } Else if(byte<0) { if(errno = =Eagain) {errno=0; Continue; } Else{perror ("recv"); Exit (Exit_failure); } } } //close the Socket objectShutdown (CLIENT_SOCKFD,2); Shutdown (SERVER_SOCKFD,2);}
Client code:
#include <stdio.h>#include<string.h>#include<errno.h>#include<sys/socket.h>#include<resolv.h>#include<stdlib.h>#include<netinet/inch.h>#include<arpa/inet.h>#include<unistd.h>#include<fcntl.h>#defineMAXBUF 128intMainintargcChar**argv) { intSOCKFD, ret, I; structsockaddr_in dest, mine; CharBuffer[maxbuf +1]; //creating a Socket object if(SOCKFD = socket (af_inet, Sock_stream,0)) <0) {perror ("Socket"); Exit (Exit_failure); } bzero (&dest,sizeof(dest)); Dest.sin_family=af_inet; Dest.sin_port= Htons (7838);//Server-specific ports, consistent with server-side settings//gets the server IP address, specified by argv[1] if(Inet_aton (argv[1], (structIN_ADDR *) &dest.sin_addr.s_addr) = =0) {perror (argv[1]); Exit (Exit_failure); } bzero (&mine,sizeof(mine)); Mine.sin_family=af_inet; Mine.sin_port= Htons (7839);//Local Port//local IP address, specified by argv[2] if(Inet_aton (argv[2], (structIN_ADDR *) &mine.sin_addr.s_addr) = =0) {perror (argv[2]); Exit (Exit_failure); } //bind your own IP address information if(Bind (SOCKFD, (structSOCKADDR *) &mine,sizeof(structSOCKADDR)) = =-1) {perror ("Bind"); Exit (Exit_failure); } //initiating a connection if(Connect (SOCKFD,structSOCKADDR *) &dest,sizeof(dest)) !=0) {perror ("Connect"); Exit (Exit_failure); } //set the SOCKFD descriptor to be non-blocking if(Fcntl (SOCKFD, F_SETFL, o_nonblock) = =-1) {perror ("Fcntl"); Exit (Exit_failure); } while(1) {bzero (buffer, Maxbuf+1); //Receiveret = recv (sockfd, buffer, MAXBUF,0);//because the socket is not blocked, the operation is non-blocking if(Ret >0) {printf ("Get%d message:%s", ret, buffer); RET=0; } Else if(Ret <0) { if(errno = =Eagain) {errno=0; Continue; } Else{perror ("recv"); Exit (Exit_failure); }} memset (buffer,' /', Maxbuf +1); printf ("input message to send:"); Fgets (buffer, maxbuf, stdin); //block at the terminal after receiving the data, sending if(ret = Send (SOCKFD, buffer, strlen (buffer),0)) == -1)//Send Data{perror ("Send"); Exit (Exit_failure); }} close (SOCKFD); return 0;}
I do experiments on different terminals of the same virtual machine
Server-side results:
Client results:
"Linux Advanced Programming" (14th) TCP Advanced applications