650 likes | 906 Views
2.3 InterProcess Communication (IPC). Part C. IPC methods. Signals Mutex ( MUTual EXclusion ) Semaphores Shared memory Memory mapped files Pipes & named pipes Sockets Message queues MPI (Message Passing Interface) Barriers. Pipes and named pipes. Pipes.
E N D
IPC methods • Signals • Mutex (MUTualEXclusion) • Semaphores • Shared memory • Memory mapped files • Pipes & named pipes • Sockets • Message queues • MPI (Message Passing Interface) • Barriers
Pipes Cmd1’s stdout becomes Cmd2’s stdin. one direction only
Pipes via pipe()(child writing to parent) // Excerpt from "Linux Programmer's Guide - Chapter 6." // (C)opyright 1994-1995, Scott Burkett #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main ( intargc, char* argv[] ) { intfd[2], nbytes; pid_tchildpid; char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd ); //fd[0] is opened for reading (input side); // fd[1] is opened for writing (output side).
Pipes via pipe()(child writing to parent) // Excerpt from "Linux Programmer's Guide - Chapter 6." // (C)opyright 1994-1995, Scott Burkett #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main ( intargc, char* argv[] ) { intfd[2], nbytes; pid_tchildpid; char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd ); //fd[0] is opened for reading (input side); // fd[1] is opened for writing (output side). if ( (childpid = fork()) == -1 ) { perror( "fork" ); exit( 1 ); }
Pipes via pipe()(child writing to parent) // Excerpt from "Linux Programmer's Guide - Chapter 6." // (C)opyright 1994-1995, Scott Burkett #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main ( intargc, char* argv[] ) { intfd[2], nbytes; pid_tchildpid; char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd ); //fd[0] is opened for reading (input side); // fd[1] is opened for writing (output side). if ((childpid = fork()) == -1) { perror( "fork" ); exit( 1 ); } if (childpid == 0) { //child process closes input side of pipe, & writes close( fd[0] ); /* Send "string" through the output side of pipe */ write( fd[1], string, (strlen(string)+1) ); } else { //parent process closes output side of pipe, & reads close( fd[1] ); /* Read in a string from the pipe */ nbytes = read( fd[0], readbuffer, sizeof(readbuffer) ); printf( "parent: received string: %s", readbuffer ); } return 0; }
Pipes via pipe()(child writing to parent) // Excerpt from "Linux Programmer's Guide - Chapter 6." // (C)opyright 1994-1995, Scott Burkett #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main ( intargc, char* argv[] ) { intfd[2], nbytes; pid_tchildpid; char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd ); //fd[0] is opened for reading (input side); // fd[1] is opened for writing (output side). if ((childpid = fork()) == -1) { perror( "fork" ); exit( 1 ); } if (childpid == 0) { //child process closes input side of pipe, & writes close( fd[0] ); /* Send "string" through the output side of pipe */ write( fd[1], string, (strlen(string)+1) ); } else { //parent process closes output side of pipe, & reads close( fd[1] ); /* Read in a string from the pipe */ nbytes = read( fd[0], readbuffer, sizeof(readbuffer) ); printf( "parent: received string: %s", readbuffer ); } return 0; } This is child writing to parent. How can we change it to be parent to child?
Pipes via pipe()(parent writing to child) // Excerpt from "Linux Programmer's Guide - Chapter 6." // (C)opyright 1994-1995, Scott Burkett #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main ( intargc, char* argv[] ) { intfd[2], nbytes; pid_tchildpid; char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd ); //fd[0] is opened for reading (input side); // fd[1] is opened for writing (output side). if ((childpid = fork()) == -1) { perror( "fork" ); exit( 1 ); } if (childpid != 0) { //parent process closes input side of pipe, & writes close( fd[0] ); /* Send "string" through the output side of pipe */ write( fd[1], string, (strlen(string)+1) ); } else { //child process closes output side of pipe, & reads close( fd[1] ); /* Read in a string from the pipe */ nbytes = read( fd[0], readbuffer, sizeof(readbuffer) ); printf( "parent: received string: %s", readbuffer ); } return 0; } That was easy!
Problem • I need to sort data but it’s complicated so I can’t use the regular sort function. • There is a program called sort that can do it for me. • But how can I use it?
Pipes via popen()(pipes to/from processes) // Excerpt from "Linux Programmer's Guide - Chapter 6." // (C)opyright 1994-1995, Scott Burkett #include <stdio.h> #define MAXSTRS 5 int main ( intargc, char* argv[] ) { FILE* pipe_fp; char* strings[ MAXSTRS ] = { "echo", "bravo", "alpha", "charlie", "delta" }; /* Create one way pipeline with call to popen() */ if (( pipe_fp = popen("sort", "w")) == NULL) { perror( "popen" ); exit( 1 ); } /* Processing loop */ for (intcntr=0; cntr<MAXSTRS; cntr++) { fputs( strings[cntr], pipe_fp ); fputc( '\n', pipe_fp ); } /* Close the pipe */ pclose( pipe_fp ); return 0; } Can be “w” or “r”. Any valid shell command.
Pipes via popen()(pipes to/from processes) // Excerpt from "Linux Programmer's Guide - Chapter 6." // (C)opyright 1994-1995, Scott Burkett #include <stdio.h> #define MAXSTRS 5 int main ( intargc, char* argv[] ) { FILE* pipe_fp; char* strings[ MAXSTRS ] = { "echo", "bravo", "alpha", "charlie", "delta" }; /* Create one way pipeline with call to popen() */ if (( pipe_fp = popen("sort", "w")) == NULL) { perror( "popen" ); exit( 1 ); } /* Processing loop */ for (intcntr=0; cntr<MAXSTRS; cntr++) { fputs( strings[cntr], pipe_fp); fputc( '\n', pipe_fp); } /* Close the pipe */ pclose( pipe_fp ); return 0; }
Pipes via popen() // Excerpt from "Linux Programmer's Guide - Chapter 6" // (C)opyright 1994-1995, Scott Burkett #include <stdio.h> #define MAXSTRS 5 int main ( intargc, char* argv[] ) { FILE* pipe_fp; char* strings[ MAXSTRS ] = { "echo", "bravo", "alpha", "charlie", "delta" }; /* Create one way pipeline with call to popen() */ if (( pipe_fp = popen("sort", "w")) == NULL) { perror( "popen" ); exit( 1 ); } /* Processing loop */ for (intcntr=0; cntr<MAXSTRS; cntr++) { fputs( strings[cntr], pipe_fp ); fputc( '\n', pipe_fp ); } /* Close the pipe */ pclose( pipe_fp ); return 0; } How would I modify this to obtain the sorted information?
Pipes via popen() // Excerpt from "Linux Programmer's Guide - Chapter 6" // (C)opyright 1994-1995, Scott Burkett #include <stdio.h> #define MAXSTRS 5 int main ( intargc, char* argv[] ) { FILE* pipe_fp; char* strings[ MAXSTRS ] = { "echo", "bravo", "alpha", "charlie", "delta" }; /* Create one way pipeline with call to popen() */ if (( pipe_fp = popen("sort > junk.dat", "w")) == NULL) { perror( "popen" ); exit( 1 ); } /* Processing loop */ for (intcntr=0; cntr<MAXSTRS; cntr++) { fputs( strings[cntr], pipe_fp ); fputc( '\n', pipe_fp ); } /* Close the pipe */ pclose( pipe_fp ); return 0; } Any valid shell command. How would I modify this to have obtain the sorted information? This works, but is junk.dat unique?
Named pipes • Named pipes • Use mkfifo command. (What is a FIFO?) • Example • mkfifomypipe • ls –l mypipe • prw------- 1 ggrevera ggrevera 0 Oct 5 21:30 mypipe • ls –l > mypipe • Hangs! Why? • Ctrl-c • ls –l > mypipe & • cat < mypipe • Doesn’t hang! Why?
Using a pipe to communicate to a child’s stdin #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/types.h> #include <unistd.h> int main ( intargc, char* argv[] ) { intfd[ 2 ]; pipe( fd ); //fd[0] is opened for reading (input side); // fd[1] is opened for writing (output side). pid_tchildpid = fork(); assert( childpid != -1 ); if (childpid == 0) { //in child process close( fd[1] ); //MUST close unused side of pipe close( 0 ); //close child's current, default stdin dup( fd[0] ); //duplicate input side of pipe to stdin //create child process //execlp( "cat", "cat", NULL ); //execlp( "sort", "sort", NULL ); execlp( "sort", "sort", "-n", NULL ); perror( "exec failed." ); //should never get here! exit( -1 ); } else { //in parent process close( fd[0] ); //close unused side of pipe //write info to pipe char buff[ 256 ]; for (inti=0; i<=10; i++) { sprintf( buff, "%d \n", i ); write( fd[1], buff, strlen(buff) ); } close( fd[1] ); //indicates that we are done int status; wait( &status ); //wait for child to finish } puts( "done." ); return 0; } parent’s fd[1] ----> child’s stdin
Named pipes • Named pipes • Use mkfifo command. (What is a FIFO?) • Example • mkfifomypipe • ls –l mypipe • prw------- 1 ggrevera ggrevera 0 Oct 5 21:30 mypipe • ls –l > mypipe • Hangs! Why? Because it waits for the reader. • Ctrl-c • ls –l > mypipe & • cat < mypipe • Doesn’t hang! Why? Because the reader executes. • Output on next slide.
Output from named pipe example • ls –l > mypipe & • cat < mypipe total 106412 -rwx------ 1 ggrevera ggrevera 14215 Oct 5 20:45 a.out drwx------ 5 ggrevera ggrevera 4096 Feb 3 2006 csc4025 drwx------ 4 ggrevera ggrevera 4096 Oct 3 09:59 csc4035 -rw------- 1 ggrevera ggrevera 194560 Sep 6 12:52 csc4035.tar -rw------- 1 ggrevera ggrevera 891 Dec 4 2005 dir.cpp . . . -rw------- 1 ggrevera ggrevera 283 Oct 5 20:44 sig.cpp [1]+ Done ls -l >mypipe Why did this finish? Because the reader reads everything.
Named pipes (Windows) • CreatePipe • Creates an anonymous pipe. • CreateNamedPipe • Creates an instance of a named pipe and returns a handle for subsequent pipe operations. A client process connects to a named pipe by using the CreateFile or CallNamedPipe function. • CallNamedPipe • Connects to a message-type pipe, writes to and reads from the pipe, and then closes the pipe. • TransactNamedPipe • Combines the functions that write a message to and read a message from the specified named pipe into a single network operation.
Sockets • Communications between systems across the network!
Sockets – client-side Steps: • socket() • creates an endpoint for communication and returns a descriptor • connect() • attempts to make a connection to another socket • call read() and/or write() • similar to an ordinary file
Sockets Grand list of standard port numbers: http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
Demo • Run cmd (the Windows command prompt). • telnet www.google.com 80 • get<enter> • GET<enter> • Note: HTTP (HyperText Transfer Protocol) is case sensitive!
Sockets – client-side(writes a message and reads a response) //---------------------------------------------------------------------- // g++ -O2 -o client.exe client.cpp -lsocket -lnsl //---------------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <netdb.h> #include <sys/types.h> //---------------------------------------------------------------------- static void error ( char* msg ) { perror( msg ); exit( 0 ); } //---------------------------------------------------------------------- int main ( intargc, char* argv[] ) { if (argc < 3) { fprintf( stderr, "usage: %s hostname port \n", argv[0] ); exit( 0 ); } //get port number from command line intportno = atoi( argv[2] ); //create an endpoint for communication intsockfd = socket( AF_INET, SOCK_STREAM, 0 ); if (sockfd < 0) error( "ERROR opening socket" ); ...
Sockets – client-side . . . //get host name from command line structhostent* server = gethostbyname( argv[1] ); if (server == NULL) { fprintf( stderr, "ERROR, no such host \n" ); exit( 0 ); } structsockaddr_inserv_addr; memset( &serv_addr, sizeof(serv_addr), 0 ); serv_addr.sin_family = AF_INET; memcpy( &serv_addr.sin_addr.s_addr, server->h_addr, server->h_length ); serv_addr.sin_port = htons( portno ); if (connect(sockfd, (structsockaddr*)&serv_addr, sizeof(serv_addr)) < 0) error( "ERROR connecting" ); . . . Mention memset and memcpy.
Sockets – client-side . . . printf( "Please enter the message: " ); char buffer[256]; memset( buffer, sizeof(buffer), 0 ); fgets( buffer, sizeof(buffer)-1, stdin ); //fgets includes \n, so we'll remove it (if necessary) if (strlen(buffer) > 0 && buffer[strlen(buffer)-1] == '\n') buffer[ strlen(buffer)-1 ] = 0; int n = write( sockfd, buffer, strlen(buffer)+1 ); //+1 to include \0 if (n < 0) error( "ERROR writing to socket" ); memset( buffer, sizeof(buffer), 0 ); n = read( sockfd, buffer, sizeof(buffer)-1 ); if (n < 0) error( "ERROR reading from socket" ); printf( "response: %s \n", buffer ); return 0; } //----------------------------------------------------------------------
Sockets – client-side (complete code) //---------------------------------------------------------------------- // g++ -O2 -o client.exe client.cpp -lsocket -lnsl //---------------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <netdb.h> #include <sys/types.h> //---------------------------------------------------------------------- static void error ( char* msg ) { perror( msg ); exit( 0 ); } //---------------------------------------------------------------------- int main ( intargc, char* argv[] ) { if (argc < 3) { fprintf( stderr, "usage: %s hostname port \n", argv[0] ); exit( 0 ); } //get port number from command line intportno = atoi( argv[2] ); //create an endpoint for communication intsockfd = socket( AF_INET, SOCK_STREAM, 0 ); if (sockfd < 0) error( "ERROR opening socket" ); //get host name from command line structhostent* server = gethostbyname( argv[1] ); if (server == NULL) { fprintf( stderr, "ERROR, no such host \n" ); exit( 0 ); } structsockaddr_inserv_addr; memset( &serv_addr, sizeof(serv_addr), 0 ); serv_addr.sin_family = AF_INET; memcpy( &serv_addr.sin_addr.s_addr, server->h_addr, server->h_length ); serv_addr.sin_port = htons( portno ); if (connect(sockfd, (structsockaddr*)&serv_addr, sizeof(serv_addr)) < 0) error( "ERROR connecting" ); printf( "Please enter the message: " ); char buffer[256]; memset( buffer, sizeof(buffer), 0 ); fgets( buffer, sizeof(buffer)-1, stdin ); //fgets includes \n, so we'll remove it (if necessary) if (strlen(buffer) > 0 && buffer[strlen(buffer)-1] == '\n') buffer[ strlen(buffer)-1 ] = 0; int n = write( sockfd, buffer, strlen(buffer)+1 ); //+1 to include \0 if (n < 0) error( "ERROR writing to socket" ); memset( buffer, sizeof(buffer), 0 ); n = read( sockfd, buffer, sizeof(buffer)-1 ); if (n < 0) error( "ERROR reading from socket" ); printf( "%s \n", buffer ); return 0; } //----------------------------------------------------------------------
Sockets – server-side Steps: • socket() • creates an endpoint for communication and returns a descriptor • bind() • this is called "assigning a name to a socket" • when a socket is created with socket, it exists in a name space (address family) but has no name assigned • listen() • To accept connections, a socket is first created with socket(), a willingness to accept incoming connections and a queue limit for incoming connections are specified with listen, and then the connections are accepted with accept(). • repeat forever: • accept() • fork() a child process that performs reads and/or writes as per ordinary file.
int accept ( int s, structsockaddr* addr, socklen_t* addrlen ); • It . . . • extracts the first connection request on the queue of pending connections, • creates a new connected socket with mostly the same properties as s, • and allocates a new file descriptor for the socket, which is returned. • The newly created socket is no longer in the listening state. • The original socket s is unaffected by this call.
Sockets – server-side /** * \file server2.cpp * \author george j. grevera * \brief A simple server in the internet domain using TCP. Runs on * polaris (but not on scott). * To compile: g++ -o server2.exe server2.cpp -lsocket */ #include <assert.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> static const int Port = 8090; static const bool Verbose = true; //---------------------------------------------------------------------- int main ( intargc, char* argv[] ) { //create an endpoint for communication if (Verbose) puts( "socket()" ); intsockfd = socket( AF_INET, SOCK_STREAM, 0 ); assert( sockfd != -1 ); …
Sockets – server-side … //assign a name to the socket structsockaddr_inserv_addr; memset( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons( Port ); if (Verbose) printf( "bind() port %d. \n", Port ); int ret = bind( sockfd, (structsockaddr*)&serv_addr, sizeof(serv_addr) ); assert( ret != -1 ); …
Sockets – server-side … //a willingness to accept incoming connections and a queue // limit for incoming connections are specified with listen if (Verbose) puts( "listen()" ); ret = listen( sockfd, 5 ); assert( ret != -1 ); …
Sockets – server-side … for ( ; ; ) { //extract the first connection request on the queue of // pending connections, create a new connected socket with // mostly the same properties as s, and allocate a new file // descriptor for the socket, which is returned if (Verbose) puts( "parent: accept()" ); structsockaddr_incli_addr; socklen_tclilen = sizeof( cli_addr ); intnewsockfd = accept( sockfd, (structsockaddr*)&cli_addr, &clilen ); assert( newsockfd != -1 ); if (Verbose) puts( "parent: fork()" ); intpid = fork(); if (pid==0) { <child process code here> } close( newsockfd ); //back in parent } return 0; } //---------------------------------------------------------------------- if (Verbose) puts( "child: begin after fork()" ); close( sockfd ); char buffer[ 256 ]; memset( buffer, 0, sizeof(buffer) ); if (Verbose) puts( "child: read()" ); int n = read( newsockfd, buffer, sizeof(buffer)-1 ); assert( n != -1 ); if (Verbose) { printf( "child: here is the message: %s \n", buffer ); puts( "child: write()" ); } char* msg = "I got your message."; n = write( newsockfd, msg, strlen(msg)+1 ); //+1 to include \0 assert( n != -1 ); close( newsockfd ); if (Verbose) puts( "child: end" ); exit( 0 ); //end child
Sockets – server-side (complete code) /** * \file server2.cpp * \author george j. grevera * \brief A simple server in the internet domain using TCP. Runs on * polaris (but not on scott). * To compile: g++ -o server2.exe server2.cpp -lsocket */ #include <assert.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> static const int Port = 8090; static const bool Verbose = true; //---------------------------------------------------------------------- int main ( intargc, char* argv[] ) { //create an endpoint for communication if (Verbose) puts( "socket()" ); intsockfd = socket( AF_INET, SOCK_STREAM, 0 ); assert( sockfd != -1 ); //assign a name to the socket structsockaddr_inserv_addr; memset( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons( Port ); if (Verbose) printf( "bind() port %d. \n", Port ); int ret = bind( sockfd, (structsockaddr*)&serv_addr, sizeof(serv_addr) ); assert( ret != -1 ); //a willingness to accept incoming connections and a queue // limit for incoming connections are specified with listen if (Verbose) puts( "listen()" ); ret = listen( sockfd, 5 ); assert( ret != -1 ); for ( ; ; ) { //extract the first connection request on the queue of // pending connections, create a new connected socket with // mostly the same properties as s, and allocate a new file // descriptor for the socket, which is returned if (Verbose) puts( "parent: accept()" ); structsockaddr_incli_addr; socklen_tclilen = sizeof( cli_addr ); intnewsockfd = accept( sockfd, (structsockaddr*)&cli_addr, &clilen ); assert( newsockfd != -1 ); if (Verbose) puts( "parent: fork()" ); intpid = fork(); if (pid==0) { if (Verbose) puts( "child: begin after fork()" ); close( sockfd ); char buffer[ 256 ]; memset( buffer, 0, sizeof(buffer) ); if (Verbose) puts( "child: read()" ); int n = read( newsockfd, buffer, sizeof(buffer)-1 ); assert( n != -1 ); if (Verbose) { printf( "child: here is the message: %s \n", buffer ); puts( "child: write()" ); } char* msg = "I got your message."; n = write( newsockfd, msg, strlen(msg)+1 ); //+1 to include \0 assert( n != -1 ); close( newsockfd ); if (Verbose) puts( "child: end" ); exit( 0 ); } close( newsockfd ); } return 0; } //----------------------------------------------------------------------
Demo • Run server on one system (brunel). • ./server2.exe • Waits for a message from the client, and then responds. • Run client (on same or different system). • ./client.exe brunel 8090 • Prompts for a message, sends message to server, and then outputs response message from server.
Message queues (Unix/Linux) #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> • MSGMAX (Linux) defines the max length of a message (~8K). • Define your message(s). • You may define many different messages of different lengths. structmyMessage { long mtype; //message type … //body of message (you decide) };
Message queues (Unix/Linux) • msgget - begin accessing (and create if necessary) a message queue int msgget ( key_t key, int msgflg ); • msgsnd - send (enqueue) a message int msgsnd ( int msqid, struct msgbuf* msgp, size_t msgsz, int msgflg ); • msgrcv - receive (dequeue) a message ssize_t msgrcv ( int msqid, struct msgbuf* msgp, size_t msgsz, long msgtyp, int msgflg ); • msgctl - misc. message queue control
Example //file: m.h //declare the message structure typedefstruct { enum { mTypeA, mTypeB, mTypeC }; long mtype; char mtext[ 256 ]; } message_buf; #define KEY 1234
Example (sender) //file: mtx.cpp #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "m.h" int main ( intargc, char* argv[] ) { // Get the message queue id for the "name" 1234, which was created by // the server. key_t key = KEY; intmsgflg = IPC_CREAT | 0666; fprintf( stderr, "\nmsgget: Calling msgget(%#lx,%#o) \n", key, msgflg ); intmsqid; if ((msqid = msgget(key, msgflg)) < 0) { perror( "msgget" ); exit( 1 ); } fprintf( stderr, "msgget: msgget succeeded: msqid = %d \n", msqid ); // We'll send message type B message_bufsbuf; sbuf.mtype = sbuf.mTypeB; strcpy( sbuf.mtext, "Did you get this?" ); //size_tbuf_length = strlen(sbuf.mtext) + 1 ; size_tbuf_length = sizeof( message_buf ); // Send a message. if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0) { printf( "%d, %d, %s, %d\n", msqid, sbuf.mtype, sbuf.mtext, buf_length ); perror( "msgsnd" ); exit( 1 ); } printf( "Message: \"%s\" Sent \n", sbuf.mtext ); return 0; }
Example (receiver) //file mrx.cpp #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <stdlib.h> #include "m.h" int main ( intargc, char* argv[] ) { // Get the message queue id for the "name" KEY, which was created by // the server. intmsqid = msgget( KEY, 0666 ); if (msqid < 0) { perror( "msgget" ); exit( 1 ); } // Receive an answer of message type B. message_bufrbuf; if (msgrcv(msqid, &rbuf, sizeof(rbuf), 0, 0) < 0) { perror( "msgrcv" ); exit( 1 ); } // Print the answer. printf( "%d %s \n", rbuf.mtype, rbuf.mtext ); exit( 0 ); }
Message queues (Windows) • Call MQOpenQueue to open the queue with send access. • Call MQSendMessage to send the message. • The MQReceiveMessage function allows you to read messages . When reading messages, you can either peek at (not removing them) or retrieve the messages (removing them) in the queue. Messages can be read either synchronously, asynchronously, or through a transaction. • Call MQCloseQueue to close the opened queue and free resources.