communicate c program and php
Asked Answered
N

4

2

I want to have a web page (written in php because it's what i know) that displays an input value. I want that value to be passed to a c programa that's already running.

I though of using sockets to communicate between both process, but how do I manage to do that? how can I use fsockopen to connect to a local socket.

Nebuchadnezzar answered 25/1, 2011 at 3:33 Comment(3)
"how can I use fsockopen to connect to a local socket." --- in the absolutely the same manner as you do this for remote ones.Stopwatch
yeah but when you connect to remote ones the format goes like this fsockopen ("www.example.com", 80, $errno, $errstr, 30). What's the format for when it's local?Nebuchadnezzar
Thks bensiu, so, when you open sockets on the local machine their id is the port right? so if I want to communicate between two process I would have to open a socket on the port let's say 1025Nebuchadnezzar
E
6

Some simple solutions I can think of are:

Redis

You could use redis as your ipc using hiredis as your c client library. I never used hiredis library before but did it just now for you to test and the library is really good. I could have known it because redis is the best piece of C code I know :).

modify example.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hiredis.h"

int main(void) {
    redisContext *c;
    redisReply *reply;

    c = redisConnect((char*)"127.0.0.1", 6379);
    if (c->err) {
        printf("Connection error: %s\n", c->errstr);
        redisFree(c);
        exit(1);
    }

    /* Blocking pop. */
    reply = redisCommand(c, "BLPOP php 0");
    if (reply->type == REDIS_REPLY_ARRAY) {
        if (reply->elements == 2) {
            printf("%s\n", reply->element[1]->str);
        }
    }
    freeReplyObject(reply);
    redisFree(c);
    return 0;
}

Compile and run example:

make
./hiredis-example

from ./redis-cli:

from another tab start start redis-cli(for prototyping) and issue the following command. You should replace this with predis as php client library, but that is going to be very easy:

lpush php "Hello from PHP"

Inside running hiredis-example:

You should see the message "Hello from PHP". Easy as pie if you ask me :).

Named pipes

You could use a named pipes.

Sockets

You could read the Beej's Guide to Network Programming Using Internet Sockets. In my opinion this is a very good read.

Eulogist answered 25/1, 2011 at 4:28 Comment(4)
how about Redis? is it fast to pick up?Nebuchadnezzar
p.s: I have never done it in C myself, but I am trying right now and compiling example just works out of the box. Now I try to make it use brpop...Eulogist
@gvalero87. It is really easy to do blocking pop from C. This hiredis library is really kickass :). I am going to update my answer for you :PEulogist
What an interesting solution. This is much better than using sockets all by yourself. Pretty simple. Great stuff.Rigger
S
2

A local socket is just a file, you'd use fopen(), fwrite(), and fclose() on it, as usual. The only difference is that you're reading from (or writing to) another process, instead of a file on disk somewhere.

Sansom answered 25/1, 2011 at 3:48 Comment(0)
A
1

You can use a named pipe.

  1. Once the external program starts running (or before that), you make sure the named pipe exists. See mkfifo.
  2. Open the pipe for reading in the external program (just like you open a regular file).
  3. Start reading the pipe. By default, the program will block until it has data to read.
  4. Open the pipe for writing in the PHP script (again, just like you would open a regular file).
  5. Write data to the pipe. The external program will now get this data.
Abdomen answered 25/1, 2011 at 4:3 Comment(0)
S
0

Here is a working example where the php script sends a request to a C daemon and then waits for the response. It uses Unix domain sockets in datagram mode so it is fast.

client.php

<?php

$file = "/tmp/myclient.sock";
unlink($file);

$socket = socket_create(AF_UNIX, SOCK_DGRAM, 0);

if (socket_bind($socket, $file) === false) {
  echo "bind failed";
}

socket_sendto($socket, "Hello world!", 12, 0, "/tmp/myserver.sock", 0);
echo "sent\n";

if (socket_recvfrom($socket, $buf, 64 * 1024, 0, $source) === false) {
  echo "recv_from failed";
}
echo "received: [" . $buf . "]   from: [" . $source . "]\n";

?>

server.c

#include <stdio.h>
#include <sys/un.h>
#include <sys/socket.h>

#define SOCKET_FILE "/tmp/myserver.sock"
#define BUF_SIZE    64 * 1024

int main() {
  struct sockaddr_un server_address = {AF_UNIX, SOCKET_FILE};

  int sock = socket(AF_UNIX, SOCK_DGRAM, 0);
  if (sock <= 0) {
      perror("socket creation failed");
      return 1;
  }

  unlink(SOCKET_FILE);

  if (bind(sock, (const struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
      perror("bind failed");
      close(sock);
      return 1;
  }

  for (;;) {
    struct sockaddr_un client_address;
    int i, numBytes, len = sizeof(struct sockaddr_un);
    char buf[BUF_SIZE];

    numBytes = recvfrom(sock, buf, BUF_SIZE, 0, (struct sockaddr *) &client_address, &len);
    if (numBytes == -1) puts("recvfrom failed");

    printf("Server received %d bytes from %s\n", numBytes, client_address.sun_path);

    for (i = 0; i < numBytes; i++)
      buf[i] = toupper((unsigned char) buf[i]);

    if (sendto(sock, buf, numBytes, 0, (struct sockaddr *) &client_address, len) != numBytes)
      puts("sendto failed");
  }

}
Seineetmarne answered 15/4, 2017 at 2:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.