Socket Signal Driver
In order for a socket to be able to use the signal-driven I/O, at least the following 3 steps are required.
- 1. Installing the Sigio signal
- 2. The owner of the socket is set to the current process. Because the Sigio signal is only sent to the socket owner process. Through Fcntl's F_setown
- 3. Sockets must be allowed to use asynchronous I/O. F_SETFL by Fcntl, set to O_async
In UDP communication, the following condition generates a Sigio signal
In TCP communication, the following conditions produce a sigio signal
Example:
The following code is strange, said to be UDP, but the send receive is sent, recv and the client is also connected to the server, that is TCP, but the socket is built with SOCK_DGRAM.
And the code can run through.
Server:
#include <stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#include<sys/types.h>#include<netinet/inch.h>#include<netinet/tcp.h>#include<sys/socket.h>#include<sys/wait.h>#include<unistd.h>#include<arpa/inet.h>#include<sys/time.h>#include<netdb.h>#include<fcntl.h>#include<signal.h>#include<sys/ioctl.h>#defineMax_lenth 1500//for Sigio signal processingStatic intNqueue =0; voidSigio_handler (intSignum) { if(Signum = =SIGIO) Nqueue++; printf ("Signum =%d, Nqueue =%d\n", Signum, Nqueue);//Print Signal Value return;}StaticRecv_buf[max_lenth];intMainintargcChar*argv[]) { intSOCKFD, on =1; structsigaction Action; sigset_t Newmask, Oldmask; structsockaddr_in ser_addr; if(ARGC! =3) {printf ("Use :%s ip_add port\n", argv[0]); Exit (Exit_failure); } memset (&SER_ADDR,0,sizeof(SER_ADDR)); Ser_addr.sin_family= Af_inet;//using IPv4Ser_addr.sin_port = htons (Atoi (argv[2])); if(Inet_aton (argv[1], (structIN_ADDR *) &ser_addr.sin_addr.s_addr) = =0) {perror (argv[1]); Exit (Exit_failure); } //Create socket if(SOCKFD = socket (af_inet, SOCK_DGRAM,0)) == -1) {perror ("Socket"); Exit (Exit_failure); } //Bind IP Address if(Bind (SOCKFD, (structSOCKADDR *) &ser_addr,sizeof(SER_ADDR)) == -1) {perror ("Bind"); Exit (Exit_failure); } memset (&action,0,sizeof(action)); Action.sa_handler=Sigio_handler; Action.sa_flags=0; //Installation SignalSigaction (SIGIO, &action, NULL); //To set the socket owner if(Fcntl (SOCKFD, F_setown, getpid ()) = =-1) {perror ("fcntl F_setown"); Exit (Exit_failure); } //set socket to signal-driven if(IOCTL (SOCKFD, Fioasync, &on) = =-1) {perror ("IOCTL Fioasync"); Exit (Exit_failure); } sigemptyset (&oldmask); Sigemptyset (&newmask); Sigaddset (&Newmask, SIGIO); printf ("Get ready\n"); while(1) { intLen; //set the current blocked signalSigprocmask (Sig_block, &newmask, &oldmask); //wait for the signal while(Nqueue = =0) Sigsuspend (&oldmask); memset (Recv_buf,' /', Max_lenth); //non-blocking receive dataLen =recv (SOCKFD, Recv_buf, Max_lenth, msg_dontwait); if(len = =-1&& errno = =eagain) Nqueue=0; //Modify the signal that the process is blockingSigprocmask (Sig_setmask, &Oldmask, NULL); if(Len >=0) printf ("recv%d byte, msg is%s\n", Len, recv_buf); } }
Client
#include <stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#include<sys/types.h>#include<netinet/inch.h>#include<netinet/tcp.h>#include<sys/socket.h>#include<sys/wait.h>#include<unistd.h>#include<arpa/inet.h>#include<sys/time.h>#include<netdb.h>#include<fcntl.h>#include<signal.h>#include<sys/ioctl.h>#defineMax_lenth 1500intMainintargcChar*argv[]) { structsockaddr_in addr; intSOCK_FD, ret; CharSnd_buf[max_lenth]; if(ARGC! =3)//parameters require the IP and port of the server{printf ("Use :%s ip_add port\n", argv[0]); Exit (Exit_failure); } memset (&ADDR,0,sizeof(addr)); Addr.sin_family=af_inet; if(Inet_aton (argv[1], (structIN_ADDR *) &addr.sin_addr.s_addr) = =0) {perror (argv[1]); Exit (Exit_failure); } addr.sin_port= Htons (Atoi (argv[2])); //Create socket if(SOCK_FD = socket (af_inet, SOCK_DGRAM,0)) == -1) {perror ("Socket"); Exit (Exit_failure); } //initiate a connection to the server?? It's not TCP, is it? if(ret = connect (SOCK_FD, (structSOCKADDR *) &addr,sizeof(addr)) == -1) {perror ("Connect"); Exit (Exit_failure); } while(1) {printf ("input msg to send:"); memset (Snd_buf,' /', Max_lenth); Fgets (Snd_buf, Max_lenth-1, stdin); Write (SOCK_FD, snd_buf, Max_lenth-1); }}
"Linux Advanced Programming" (15th) UDP Network Programming Application 4