Перевести код: C Socket в PHP Socket - PullRequest
1 голос
/ 06 июня 2011

Я просмотрел прошлые темы здесь, чтобы найти любые соответствующие темы, касающиеся сокетов C, переводимых в сокеты PHP, и я подробно изучил руководства php.net и C, чтобы выяснить, как преобразовать некоторый исходный код C, который у меня есть, в Исходный код PHP с подключением к удаленному сокету.

Источник, который я собираюсь опубликовать, находится на C. Этот код уже работает и подтвержден для работы в скомпилированном .exe, который написал один из моих программистов. Он не знает PHP, для которого я создаю новую программу, для которой требуется этот фрагмент.

Программа делает это: создает сокет-соединение с удаленным сервером / портом, отправляет размер файла изображения, который необходимо отправить на сервер, а затем я предполагаю, что когда сервер знает размер файла, программа отправляет двоичные данные изображения и размер файла изображения снова (например, функция загрузки на сервер через сокеты). Затем он использует recv (); функция в C, чтобы получить байты обратно определенной длины.

В основном это отправка изображения с чем-то зашифрованным внутри него. На сервере уже запущена программа на указанном порту, которая расшифровывает образ. Затем сокет отправляет обратно этот расшифрованный текст. У меня нет доступа к алгоритму дешифрования, иначе я бы не использовал сокеты, очевидно.

Вот источник C, который мне прислали, и мои последующие попытки в PHP перевести его правильно.

// В этом коде C есть длинный размер; переменная, которая используется внизу, но никогда не инициализируется. Я не знаю, что с этим делать. Некоторые другие переменные также никогда не используются.

function picBin()
assume curlBinaryData variable pic is filled with binary data from picture download.
pic->currentSize is set to the size of the image

в случае успеха вернет 0. также char * word в параметрах функции будет установлено на дешифрование картинки

// структура данных bin, которую я использую для быстрой загрузки гетто, просто чтобы вы знали, как она выглядит

struct curlBinaryData{
    char *data;
    int currentSize;
    int maxSize;
};

int picBin(curlBinaryData *pic, char *word, int threadNum,
           char *host, unsigned short port)
{
    char data1[1000], data2[1000],
         temp[1000], printBuf[1000], buffer[1000], *p, *p2;
    int num, a, totalBytes;
    long size;
    char *pSize;
    SOCKET sock;

    while ((sock = connectSocket(host, port)) == INVALID_SOCKET)
    {
        sprintf(printBuf, "Could not connect(picBin) %s:%d\n", host, port);
        print_ts(printBuf, "red");
        //Sleep(15000);
    }

    buffer[0]='\0';
    send(sock, buffer, 1, 0);

    pSize=(char *)&(pic->currentSize);
    send(sock, pSize, 4, 0);

    send(sock, pic->data, pic->currentSize, 0);

    totalBytes=0;
    do{ 
        if ( (num=recv(sock, data1+totalBytes, 1, 0)) > 0)
            totalBytes+=num;
    } while( (totalBytes<4) && (num>0) );

    pSize=(char *)&size;
    if (totalBytes==4){ //got 4 bytes for dword
        memcpy(pSize, data1, 4);
        if (size==1)
        {
            totalBytes=0;
            do
            {
                if ( (num=recv(sock, data1+totalBytes, 1, 0)) > 0)
                    totalBytes+=num;
            } while( (totalBytes<4) && (num>0) );
            memcpy(pSize, data1, 4);
            if (totalBytes==4)
            { //got 4 bytes for dword
                totalBytes=0;
                for (a=0; ( (a<size) && (num>0) ); a++)
                {
                    if ( (num=recv(sock, data1+totalBytes, 1, 0)) > 0)
                        totalBytes+=num;
                }
                if (totalBytes==size)
                {
                    closesocket(sock);
                    data1[totalBytes]='\0';
                    strcpy(word, data1);

                    return 0; //0 on success
                }
            }
        }
    }
    closesocket(sock);
    return -1; //something errord
}

Теперь вот мой PHP-код, который я пытался:

if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false)
{
  echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
}

if (socket_connect($sock, $host, $port) === false)
{
  echo "socket_connect() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}

socket_send($sock, '\0', 1, MSG_EOF);

$ci = file_get_contents($picURL);
$ciwrite = fopen('pic.jpg', 'w+');
fwrite($ciwrite, $ci);
fclose($ciwrite);

$picFileSize = filesize('pic.jpg');

socket_send($sock, $picFileSize, 4, MSG_EOF);

socket_send($sock, $ci, $picFileSize, MSG_EOF);

$num = socket_recv($sock, $totalBytes, 1, MSG_DONTWAIT);

print $num; // this doesn't even Print anything to my console when I execute it via CLI

/*do{
    if (($num = socket_recv($sock, $totalBytes, 1)) > 0)
    {
      $totalBytes += $num;
    }
  } while(($totalBytes &lt; 4) && ($num > 0));*/

Ответы [ 2 ]

0 голосов
/ 01 сентября 2016
    buffer[0]='\0';
    send(sock, buffer, 1, 0);

socket_send($sock, '\0', 1, MSG_EOF);

escape-последовательности обратной косой черты, отличные от \' и \\, не раскрываются в одиночных кавычках; таким образом, '\0' является строкой из двух символов \ и 0, а вышеприведенный socket_send() отправляет символ \.
MSG_EOF без эффекта в лучшем случае и вредно в худшем случае; лучше не используйте его.
Правильный перевод:

  socket_send($sock, "\0", 1, 0);
    pSize=(char *)&(pic->currentSize);
    send(sock, pSize, 4, 0);

socket_send($sock, $picFileSize, 4, MSG_EOF);

Приведенный выше socket_send() отправляет первые 4 символа строкового представления ASCII $picFileSize, потому что socket_send() ожидает string в качестве второго аргумента и, следовательно, данное integer приводится в строку . Для отправки 4-байтового двоичного файла целое число :

  socket_send($sock, pack("L", $picFileSize), 4, 0);
$num = socket_recv($sock, $totalBytes, 1, MSG_DONTWAIT);

print $num; // this doesn't even Print anything to my console when I execute it via CLI

Неудивительно, что вы не получите никаких данных, если вы DONTWAIT .
Рабочий перевод для принимающей части программы C:

$totalBytes = socket_recv($sock, $data1, 4, MSG_WAITALL);
if ($totalBytes==4)
{ //got 4 bytes for dword
    $size = unpack("L", $data1);
    if ($size[1]==1)
    {
        $totalBytes = socket_recv($sock, $data1, 4, MSG_WAITALL);
        if ($totalBytes==4)
        { //got 4 bytes for dword
            $size = unpack("L", $data1);
            $totalBytes = socket_recv($sock, $data1, $size[1], MSG_WAITALL);
            if ($totalBytes==$size[1])
            {
                echo $data1, "\n";
            }
        }
    }
}
0 голосов
/ 06 июня 2011

относительно сокетов C, переводимых в сокеты PHP

Сокеты реализуются ОС, а не языком.Нет такой вещи, как сокет C или PHP.

Когда вы вызываете socket_send из PHP, он преобразует сообщение в строку (если это еще не так).

pSize=(char *)&(pic->currentSize);
send(sock, pSize, 4, 0);

WTF?Предполагая, что pic-> currentSize содержит строковое представление, если изображение почему-то жестко закодировано в 4 байта!

Но здесь:

send(sock, pic->data, pic->currentSize, 0);

pic-> currentSize должно содержать целочисленное значение.Перемещение (char *) перед указателем на целое число (или long, так как это выглядит так, как объявляется размер) НЕ ДЕЛАЕТ ЕГО СТРОКОЙ.Это все еще указатель.Хорошо, 32-битный указатель будет 4 байта - но WTF - это указатель, отправляемый через сокет ???Если только здесь не происходит какая-то странная перегрузка, а на самом деле это C ++, а не C.

При дальнейшем чтении он отправляет указатель на удаленный конец, затем считывает 4-байтовое значение и считает операцию успешной, если она соответствуетуказатель....!!AAARRGGHHH!даже если бы он отправлял размер, эта проверка целостности полностью избыточна через сокет Unix или INET.

Я бы покопался еще немного, но попытка разобраться в этом будет пустой тратой времениС кодом.Используйте сетевой анализатор, чтобы выяснить, что на самом деле здесь происходит;не используйте этот код на C в качестве какой-либо модели написания собственного клиента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...