Can I have two apps exchange messages over stdin/stdout?

Hello,

If I implement two apps using asynchronous I/O ( select() ) so both apps will write into stdout and they will read each others output, is going to work?

I guess it's not possible to implement such thing just using pipes & output redirection?

-Thank you.

EDIT: I need a bidirectional communication between two processes, one of them is multithreaded.
Last edited on
AFAIK the thing is that each program starts in different process. Processes haves their own stdins/stdouts controlled via OS.

-e-
I guess it's not possible to implement such thing just using pipes & output redirection?
That's exactly what pipes are for.

See the example here where one program spawns another (ls in this example) and talks to it over a pipe.
http://pubs.opengroup.org/onlinepubs/009604499/functions/popen.html

I forgot to add the link, oops.
Last edited on
Hi kbw, what example?
By pipes I meant:

 
ProgramA | ProgramB
kbw, I got your example, it's uni-directional for reading only. I need a two-way communication to read/write. I guess I have to open two pipes - one for reading and another for writing. Not sure how - trying to google for now. If you also have a two-directional sample please post. Thank you.
Sorry, wrong example. Take a look at this.
http://pubs.opengroup.org/onlinepubs/009604599/functions/pipe.html
I got it - it works!

Is it also possible to read from stdin, meaning while these two apps communicate through the pipes with each other, I could also enter a command to send it to a child?



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <unistd.h>
#include <stdio.h>
#include <cstdlib>

main()
{
    int outfd[2];
    int infd[2];

    pipe(outfd);                /* Where the parent is going to write to */
    pipe(infd);                 /* From where parent is going to read */

    if(!fork())                                 // code executed by child.
    {
        close(STDOUT_FILENO);
        close(STDIN_FILENO);
        dup2(outfd[0], STDIN_FILENO);
        dup2(infd[1], STDOUT_FILENO);
        close(outfd[0]);                        /* Not required for the child */
        close(outfd[1]);
        close(infd[0]);
        close(infd[1]);
        system("/usr/bin/bc -q");
    }
    else                                        // code executed by parent.
    {

        for( ;; )
        {
            char input[100];
            close(outfd[0]);                        /* These are being used by the child */
            close(infd[1]);

            write(outfd[1], "2^32\n", 5);             /* Write to child’s stdin */
            printf("%s", "2^32\n");

            input[read(infd[0], input, 100)] = 0;     /* Read from child’s stdout */
            printf("%s", input); fflush(stdout);

            close(outfd[1]);
            close(infd[0]);

            printf("\n");

            sleep(5);
        }

    }
}
Last edited on
Is this what you want? bc is controlled from the parent, which echoes commands from stdin.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <unistd.h>
#include <stdio.h>
#include <cstdlib>
#include <cstring>

int main()
{
        /* Where the parent is going to write to */
        int outfd[2];
        pipe(outfd);

        /* From where parent is going to read */
        int infd[2];
        pipe(infd);

        if (fork() == 0)        // code executed by child.
        {
                close(STDOUT_FILENO);
                close(STDIN_FILENO);
                dup2(outfd[0], STDIN_FILENO);
                dup2(infd[1], STDOUT_FILENO);
                close(outfd[0]);/* Not required for the child */
                close(outfd[1]);
                close(infd[0]);
                close(infd[1]);

                char* argv[] = { "/usr/bin/bc", "-q", 0 };
                execvp(argv[0], argv);
        }

        // code executed by parent.
        close(outfd[0]);        /* These are being used by the child */
        close(infd[1]);

        for (bool done = false; !done; )
        {
                char input[100] = "";
                gets(input);
                strcat(input, "\n");
                write(outfd[1], input, strlen(input));
                done = strcmp(input, "quit\n") == 0;

                memset(input, 0, sizeof(input));
                read(infd[0], input, sizeof(input));    /* Read from child’s stdout */
                printf("%s", input);
                fflush(stdout);
        }

        close(outfd[1]);
        close(infd[0]);
        return 0;
}
Not quite - I want the parent and child to keep communicating. So in the code from my post it should keep printing the value of 2^32 every five seconds, but I'd also like to be able to enter my own expression in between those five seconds so it should be send to bc for calculation and the result should be sent back.

So, the output would be like:

4294967296 <- start

4294967296 <- 5 sec

2^4 <- I manually entered this at e.g. second 6
16 <- bc calculated this

4294967296 <- second 10.


kbw, I appreciate your help, you do not have to code it for me just point in the right direction, unless it takes you like 2 minutes :). I am a bit stuck in here to tell the truth. I am going over Richard Stevens right now but I do not see he has what I need, books differ from real life. Thanks again.
Last edited on
You could use alarm() to send a SIGALRM signal every five seconds.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <unistd.h>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <signal.h>

int outfd[2];
int infd[2];

void alarmed(int sig)
{
	if (sig == SIGALRM)
	{
		char input[100] = "2^32\n";
		write(outfd[1], input, 5);

		memset(input, 0, sizeof(input));
		read(infd[0], input, sizeof(input));	/* Read from child’s stdout */
		printf("%s", input);
		fflush(stdout);

		alarm(5);
	}
}

int main()
{
	/* Where the parent is going to write to */
	pipe(outfd);

	/* From where parent is going to read */
	pipe(infd);

	if (fork() == 0)	// code executed by child.
	{
		close(STDOUT_FILENO);
		close(STDIN_FILENO);
		dup2(outfd[0], STDIN_FILENO);
		dup2(infd[1], STDOUT_FILENO);
		close(outfd[0]);/* Not required for the child */
		close(outfd[1]);
		close(infd[0]);
		close(infd[1]);

		char* argv[] = { "/usr/bin/bc", "-q", 0 };
		execvp(argv[0], argv);
	}

	// code executed by parent.
	close(outfd[0]);	/* These are being used by the child */
	close(infd[1]);

	signal(SIGALRM, alarmed);
	alarm(5);
	for (bool done = false; !done; )
	{
		char input[100] = "";
		gets(input);
		strcat(input, "\n");
		write(outfd[1], input, strlen(input));
		done = strcmp(input, "quit\n") == 0;

		memset(input, 0, sizeof(input));
		read(infd[0], input, sizeof(input));	/* Read from child’s stdout */
		printf("%s", input);
		fflush(stdout);
	}

	close(outfd[1]);
	close(infd[0]);
}
Last edited on
It works, just one question, if I press Enter without providing any input it won't take any more input from me so I have to restart the program, do you know why is that? - THX
Last edited on
It's the beviour of bc. If you want to fix it, you have to validate the string passed to bc on the pipe.
I can catch Enter but bc run on its own takes Enter no problem, I'll look it at more.
Last edited on
kbw - thanks a lot for your time!
Topic archived. No new replies allowed.