communicate c program and php

和自甴很熟 提交于 2019-11-27 14:15:02

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.

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.

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.

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

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!