Communication between Erlang and Unix proceses
Raimo Niskanen
raimo@REDACTED
Tue Oct 28 08:21:01 CET 2003
Hi.
To close a port;
Port ! {self(),close},
receive {Port,closed} -> ok end,
Not the other way around, and note that you receive the atom 'closed',
not the string "close". Or have a look at erlang:port_close(Port).
If the port program closes the port you will receive
{'EXIT',Port,Reason} unless you use the flag 'eof' to open_port/2, in
which case you will receive {Port,eof} and then will have to close the
port yourself.
About the fgets(): I think the problem is that you try to fgets() from
stderr, which is an input stream for the port program. Who knows what
gets messed up then.
Erlang uses file descriptors 0 and 1 (stdin and stdout) to communicate
with the port program, so the port program's file descriptors 0 and 1
are connected to the Erlang port. Basta.
You can also use the flag 'stderr_to_stdout' to open_port/2 to duplicate
the port program's stdout to stderr, so also the stderr output comes to
the Erlang port. Not that I think you want it...
You can also use the flag nouse_stdio to make erlang use file
descriptors 3 and 4 instead of 0 and 1, and then fix your port program
to do the same and so get access to stdin and stdout from the port
program. Exactly how it is done I do not know (yet).
Have a look at http://www.erlang.org/download/erlang-book-part1.pdf
section "9.4 Ports" (page 134), and the erlang man page for 'erlang',
functions open_port/2 and port_close/1.
--
/ Raimo Niskanen, Erlang/OTP, Ericsson AB
mwilligs@REDACTED wrote:
> Hi there,
>
> I have been trying the communication between Unix proceses
> and Erlang processes through the usage of the open_port
> function. But, I have been having some problems to receive
> the messages from the Unix process.
> I can’t discriminate when I received a message and when no message is
> received. Please, take a look at the source files: con2.c and con1.erl
> The erlang process receives 11 messages “Hello” through the port, and then
> I tried to close the port, but it did not work. How should I do that?
>
> And, if you take a look at the programs con3.c and con2.erl, you will see
> that I tried to receive messages that were suppose to be written from the
> Unix Console through fgets(buf, 1000, stderr) call. But, instead of that I
> am not being able to write the message and the Erlang process reads
> garbage from the port.
> How can I discriminate when a real message is received?
>
> Thanks again,
> Miguel Willigs
>
>
> Files attached:
> ===============
>
>
> -module(con1).
> -export([read/0]).
>
>
> %write (Path, Data) ->
> %Port = open_port({spawn, Path}, [{packet, 2}]),
> %Port ! {self(), {command, Data}}.
>
> read () ->
> Port = open_port({spawn, "/home/ljara/erlang/con2"}, [{packet, 2}]),
> recibir().
>
> recibir() ->
>
> receive
> {Port, Data} ->
> io:format('erlang received from port:~p~n', [Data]),
> recibir(),
>
> receive
> {Port, "close"} ->
> Port ! {self(), close}
>
> end
> end.
>
>
> *****************************************************************************************************************************************************
>
>
> /*********************************************************************/
> /* con2.c - Programa que recibe mensajes desde un programa Erlang */
> /* Fecha: 24/10/23 */
> /* Autor: IYDDEPTO */
> /*********************************************************************/
>
> #include <stdio.h>
> #include <string.h>
>
>
> /****************************************/
>
> typedef unsigned char byte;
>
> //Funciones
> void put_int16(int i, byte *s);
>
>
> /****************************************/
>
> int main()
> {
> int len, flag=0, i=0;
>
> byte buf[1000];
>
> char ini_message[50];
>
> strcpy(ini_message, "com2 in C Starting \n");
>
> strcpy(buf, "Hello");
>
> fprintf(stderr, ini_message);
>
> while (flag!=1 && i<10)
> {
> //gets(buf);
> // fgets(buf, 1000, stderr);
>
> //Si ya no se quiere enviar mensajes
> if(strcmp(buf, "fin")==0)
> {
> flag=1;
> //Se cierra el puerto
> fprintf(stderr, "I have touched the flag\n");
> }
>
> if((write_cmd(buf, strlen(buf)))<0)
> {
> perror("Message Sending Failed");
> exit(1);
> }
> i++;
> fprintf(stderr, "Valor de i:%d\n", i);
> }
>
> if((write_cmd("close", strlen("close")))<0)
> {
> perror("Message Sending Failed");
> exit(1);
> }
>
> fprintf(stderr, "C Program finished\n");
> return(0);
> }
>
> /***************************************************/
>
> /* Pack the 2 bytes length (MSB first) and send it */
> int write_cmd(byte *buf, int len)
> {
> byte str[2];
>
> put_int16(len, str);
>
> if (write_exact(str, 2) != 2)
> return(-1);
>
> return write_exact(buf, len);
>
> }
>
> /***************************************************/
>
> int write_exact(byte *buf, int len)
> {
> int i, wrote = 0;
>
> i = write(1, buf+wrote, len-wrote);
> return (i);
>
>
> }
>
> /***************************************************/
>
> void put_int16(int i, byte *s)
> {
> *s = (i >> 8) & 0xff;
> s[1] = i & 0xff;
> }
>
>
> ******************************************************************************************************************************************************
>
> -module(con2).
> -export([read/0]).
>
>
> %write (Path, Data) ->
> %Port = open_port({spawn, Path}, [{packet, 2}]),
> %Port ! {self(), {command, Data}}.
>
> read () ->
> Port = open_port({spawn, "/home/ljara/erlang/con3"}, [{packet, 2}]),
> recibir().
>
> recibir() ->
>
> receive
> {Port, Data} ->
> io:format('erlang received from port:~p~n', [Data]),
> recibir(),
>
> receive
> {Port, "close"} ->
> Port ! {self(), close}
>
> end
> end.
>
>
> ******************************************************************************************************************************************************
>
> /*********************************************************************/
> /* con3.c - Programa que recibe mensajes desde un programa Erlang */
> /* Fecha: 24/10/23 */
> /* Autor: IYDDEPTO */
> /*********************************************************************/
>
> #include <stdio.h>
> #include <string.h>
>
>
> /****************************************/
>
> typedef unsigned char byte;
>
> //Funciones
> void put_int16(int i, byte *s);
>
>
> /****************************************/
>
> int main()
> {
> int len, flag=0, i=0;
>
> byte buf[1000];
>
> char ini_message[50];
>
> strcpy(ini_message, "com2 in C Starting \n");
>
> //strcpy(buf, "Hello");
>
> fprintf(stderr, ini_message);
>
> while (flag!=1 && i<10)
> {
> //gets(buf);
> fgets(buf, 1000, stderr);
>
> //Si ya no se quiere enviar mensajes
> if(strcmp(buf, "fin")==0)
> {
> flag=1;
> //Se cierra el puerto
> fprintf(stderr, "I have touched the flag\n");
> }
>
> if((write_cmd(buf, strlen(buf)))<0)
> {
> perror("Message Sending Failed");
> exit(1);
> }
> i++;
> fprintf(stderr, "Valor de i:%d\n", i);
> }
>
> if((write_cmd("close", strlen("close")))<0)
> {
> perror("Message Sending Failed");
> exit(1);
> }
>
> fprintf(stderr, "C Program finished\n");
> return(0);
> }
>
> /***************************************************/
>
> /* Pack the 2 bytes length (MSB first) and send it */
> int write_cmd(byte *buf, int len)
> {
> byte str[2];
>
> put_int16(len, str);
>
> if (write_exact(str, 2) != 2)
> return(-1);
>
> return write_exact(buf, len);
>
> }
>
> /***************************************************/
>
> int write_exact(byte *buf, int len)
> {
> int i, wrote = 0;
>
> i = write(1, buf+wrote, len-wrote);
> return (i);
>
>
> }
>
> /***************************************************/
>
> void put_int16(int i, byte *s)
> {
> *s = (i >> 8) & 0xff;
> s[1] = i & 0xff;
> }
>
>
>
>
More information about the erlang-questions
mailing list