общаться c программой и php - PullRequest
2 голосов
/ 25 января 2011

Я хочу иметь веб-страницу (написанную на php, потому что это то, что я знаю), которая отображает входное значение.Я хочу, чтобы это значение было передано в программу AC, которая уже запущена.

Хотя я и использовал сокеты для связи между обоими процессами, но как мне это сделать?Как я могу использовать fsockopen для подключения к локальному сокету.

Ответы [ 4 ]

6 голосов
/ 25 января 2011

Вот несколько простых решений, которые я могу придумать:

Redis

Вы можете использовать redis в качестве ipc, используя hiredis в качестве клиентской библиотеки c. Я никогда раньше не использовал библиотеку hiredis, но сделал это сейчас, чтобы вы могли протестировать, и библиотека действительно хороша. Я мог бы знать это, потому что redis - лучший фрагмент кода на C, который я знаю :).

изменить пример.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;
}

Пример компиляции и запуска:

make
./hiredis-example

от ./redis-cli:

из другой вкладки запустите redis-cli (для создания прототипа) и введите следующую команду. Вам следует заменить это на predis в качестве клиентской библиотеки php, но это будет очень просто:

lpush php "Hello from PHP"

Пример hiredis для внутреннего использования:

Вы должны увидеть сообщение "Hello from PHP". Легко, как пирог, если вы спросите меня:).

Именованные трубы

Вы можете использовать именованные каналы .

Головки

Вы можете прочитать Руководство Beej по сетевому программированию с использованием интернет-сокетов . На мой взгляд, это очень хорошее чтение.

2 голосов
/ 25 января 2011

Локальный сокет - это просто файл, вы будете использовать fopen(), fwrite() и fclose() на нем, как обычно.Единственное отличие состоит в том, что вы читаете (или пишете) другой процесс, а не файл на диске где-то.

1 голос
/ 25 января 2011

Вы можете использовать именованный канал.

  1. Как только запускается внешняя программа (или до этого), вы убедитесь, что именованный канал существует. См. mkfifo .
  2. Открыть канал для чтения во внешней программе (как вы открываете обычный файл).
  3. Начните читать трубу. По умолчанию программа будет блокироваться до тех пор, пока не получит данные для чтения.
  4. Откройте канал для записи в сценарии PHP (опять же, как вы бы открыли обычный файл).
  5. Запись данных в канал. Внешняя программа теперь получит эти данные.
0 голосов
/ 15 апреля 2017

Вот рабочий пример, когда скрипт php отправляет запрос демону C, а затем ожидает ответа.Он использует доменные сокеты Unix в режиме дейтаграмм, поэтому работает быстро.

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

}
...