gvalero87
gvalero87

Reputation: 875

communicate c program and php

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.

Upvotes: 2

Views: 6069

Answers (4)

Bernardo Ramos
Bernardo Ramos

Reputation: 4577

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");
  }

}

Upvotes: 0

Alfred
Alfred

Reputation: 61771

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.

Upvotes: 6

Artefacto
Artefacto

Reputation: 97805

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.

Upvotes: 1

Marc B
Marc B

Reputation: 360562

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.

Upvotes: 2

Related Questions