Linux select System Call _ 2, select System Call _ 2

Source: Internet
Author: User

Linux select System Call _ 2, select System Call _ 2

In the previous blog, we have three clients in our program, so we have created three pipelines in advance. Each client uses one pipeline to send messages to the server. When the select system is called on the server side, the server reads a message from a certain pipeline and displays it on the standard output.

In this article, we will allow the server to have a pipeline specifically used to receive messages from the client (publish notifications, send messages to be forwarded by the server, and deprecate notifications ). The server needs to maintain a list (using struct) to record which users have connected to the server for receiving messages. When the client starts, it will send a publish message to the server and send its pid to the server. The server will add it to the list and forward the message to the client on the list. At the same time, the client needs to create an MPS queue to receive messages forwarded by the server. Note that you need to inform the server of the MPs queue name so that the server can open the MPs queue write end, the name of the notification queue can be sent when the client sends an online message to the server. When the client is deprecated, it also needs to notify the server so that the server can delete it from the list, so that it will not send messages to it later. If the message is not deleted, the server will send a message to a closed-read-end pipeline, causing the server to crash! (PIPE signal)

Note:

Assume that there are three clients. The pipeline used by the server to receive messages is called. Because the server only has one pipeline A to receive messages sent from the client, all clients will enable the write end on the other end of the pipeline. That is to say, the three write ends of all clients have one read end to the server. In the previous blog, we know that select listens to pipelines by blocking or not. Only when the MPs queue is not blocked can select obtain the message and set the file descriptor in fd_set to 1. When three write ends have one read end, the non-blocking conditions are as follows:

1. When the write end of any client sends a message to the pipeline, the pipeline is not blocked. select can listen and read returns the number of words read.

2. All three write ends are closed. The pipeline is not blocked. select can be listened to, and read returns 0. Note: If you only disable the write end of a client, select cannot be detected because select can only detect non-blocking conditions.

In the case that non-blocking is 1 or 2, select does not know, we need to determine by ourselves, usually through the read return value judgment. When the returned read value is 0, we will use continue in the if statement. Because the server cannot be mounted, the read end closed by the client can be enabled later.

Server. c
/*************************************** * *********************************> File Name: server. c> Author: KrisChou> Mail: zhoujx0219@163.com> Created Time: sat 23 Aug 2014 05:08:48 pm cst ********************************* ***************************************/ # include <stdio. h> # include <stdlib. h> # include <string. h> # include <sys/types. h> # include <sys/stat. h> # include <fcntl. h> # include <dirent. h> # I Nclude <unistd. h> # include <sys/time. h> # include <sys/select. h> typedef struct tag {int s_id;/* process ID */int s_fd;/* process descriptor */int s_flag;/* whether the user in the server list is valid */} USR, * pUSR; int main (int argc, char * argv []) {/* open Pipeline */int fd_server; fd_server = open (argv [1], O_RDONLY ); if (fd_server =-1) {perror ("error"); exit (1) ;}/ * initialize the server user list */USR ulist [1024]; memset (ulist, 0, sizeof (ulist);/* defines the parameters of the select Parameter */Fd_set read_set, ready_set;/* ready_set is the backup of read_set */FD_ZERO (& read_set);/* clear fd_set */FD_SET (fd_server, & read_set ); /* Add the server's MPs queue for receiving messages to the listening Set */struct timeval tm;/* select round robin time */int nret; /* record the select return value */char buf [1024];/* store the messages read from the pipeline */while (1) {/* reset the select parameters */tm. TV _sec = 0; tm. TV _usec = 1000; ready_set = read_set; nret = select (fd_server + 1, & ready_set, NULL, NULL, & tm);/* in se If the pipeline is blocked during the lect round time, nret returns 0 */if (nret = 0) {continue;} if (FD_ISSET (fd_server, & ready_set )) // In fact, if can be omitted here, because only one pipeline is listened {// nret is not 0, it must be that the pipeline is not blocked by memset (buf, 0, 1024 ); if (0 = read (fd_server, buf, 1024) {continue;} else {if (strncmp (buf, "on", 2) = 0) // on pid {int pid; char pipename [32] = ""; // store the pipe name sscanf (buf + 3, "% d", & pid ); // pipeline name pid. pipe name: printf ("% d on \ n", pid); // output the customer's online message to the sprintf (pipename ," % D. fifo ", pid);/* Find an invalid struct from the user list and save it to */int index; for (index = 0; index <1024; index ++) {if (ulist [index]. s_flag = 0) {break;} if (index = 1024) {printf ("full! \ N ");} else {ulist [index]. s_id = pid; ulist [index]. s_fd = open (pipename, O_WRONLY);/* open the write end of the server to forward messages to the client */ulist [index]. s_flag = 1 ;}} else if (strncmp (buf, "off", 3) = 0) // off pid {int pid; sscanf (buf + 4, "% d", & pid); printf ("% d off! \ N ", pid); int index; for (index = 0; index <1024; index ++) {if (ulist [index]. s_id = pid) {ulist [index]. s_flag = 0; close (ulist [index]. s_fd); break ;}}else {int index; for (index = 0; index <1024; index ++) {if (ulist [index]. s_flag = 1) {write (ulist [index]. s_fd, buf, strlen (buf ));}}}}}}}
Client. c
/*************************************** * *********************************> File Name: client. c> Author: KrisChou> Mail: zhoujx0219@163.com> Created Time: sat 23 Aug 2014 09:21:02 am pdt ********************************* ***************************************/ # include <stdio. h> # include <sys/types. h> # include <sys/stat. h> # include <unistd. h> # include <stdlib. h> # include <string. h> # include <fcntl. h> int main (Int argc, char * argv []) {/* open the pipeline for uploading messages to the server */int fd_send; fd_send = open (argv [1], O_WRONLY ); if (fd_send =-1) {perror ("open"); exit (1 );} /* Be sure to create the client's own pipeline before sending the online message to the server. Otherwise, the server cannot find the Pipeline * // * pipename stores the pipeline created by the client, the name must be a pid. fifo */char pipename [32] = ""; sprintf (pipename, "% d. fifo ", getpid ();/* The client creates a message receiving Pipeline */if (-1 = mkfifo (pipename, 0666) {perror (" mkfifo "); exit (1);}/* write online messages to the MPs queue */char msg [1024] = ""; sp Rintf (msg, "on % d! \ N ", getpid (); write (fd_send, msg, strlen (msg);/* open the pipeline of the client */int fd_rcv; fd_rcv = open (pipename, o_RDONLY); if (fd_rcv =-1) {perror ("open client"); exit (1 );} /* the sub-process is used to receive messages forwarded by the server */if (fork () = 0) {close (fd_send); while (memset (msg,), read (fd_rcv, msg, 1024)> 0) {printf ("msg >>:"); fflush (stdout); write (1, msg, strlen (msg ));} /* When the client goes offline, the server deletes it from the list and closes the write end of the client pipeline. When the server closes the write end of the pipeline, it exits the while LOOP */close (fd_rcv); exit (1 );} /* the parent process is used to send messages */close (fd_rcv); while (memset (msg, 1024), fgets (msg, stdin )! = NULL) {write (fd_send, msg, strlen (msg);}/* press ctrl + D to exit the loop, and then the client goes offline */memset (msg ); sprintf (msg, "off % d \ n", getpid (); write (fd_send, msg, strlen (msg); close (fd_send); wait (NULL );}
Run the program and enter:
make 1.fifo./server.exe 1.fifo./client.exe 1.fifo./client.exe 1.fifo...

Use of select in linux

The select () function modifies the value of the variable TV. You need to set TV again before calling the select () function.
Or you can use pselect ()

How many times does the select () function run in the next Linux applet?

The reason is simple.

Because, after you press the next key, there is data in the buffer, that is, there is an event in stdin, that is, there is data.
You have never performed any operations on the buffer, so stdin remains in the data state.

If you use fflush to clear the buffer after a select statement is returned, or use input functions such as scanf and getchar to obtain the data in the buffer, the stdin buffer will have nothing to do with the data, select again, And the status is waiting for the event to happen.

For insurance, you assign a TV value every time.
TV. TV _sec = 2;
TV. TV _usec = 0;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.