翻译代码:C套接字到PHP套接字

时间:2011-06-06 05:17:18

标签: php c sockets

我查看了这里的过去的线程,找到有关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 *字也将被设置为pic的解密

// bin数据结构我用于快速的ghetto下载功能,只是让你知道它看起来如何

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 :(得分:0)

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

\'\\以外的反斜杠转义序列不会在单引号字符串中展开;因此,'\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()发送$picFileSize的ASCII字符串表示的前4个字符,因为socket_send()期望字符串作为其第二个参数,因此给定整数被强制转换为字符串。发送一个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";
            }
        }
    }
}

答案 1 :(得分:-1)

  

关于C套接字被转换为PHP套接字

套接字由操作系统实现 - 而不是语言。没有C套接字和PHP套接字。

当你从PHP调用socket_send时,它会将消息转换为字符串(如果它不是一个字符串)。

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

WTF?假设pic-&gt; currentSize包含一个字符串表示,如果图像为什么硬编码为4个字节!

但是在这里:

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

pic-&gt; currentSize必须包含整数值。在指向整数(或长,因为看起来是'大小'的声明)的指针前面推(char *)不要让它成为一个字符串。它仍然是一个指针。 OK一个32位指针将是4个字节 - 但WTF是一个通过套接字发送的指针???除非这里有一些奇怪的重载,这实际上是C ++而不是C。

进一步读取它会将指针发送到远程端,然后读回一个4字节的值,如果它与指针匹配则认为操作成功.... !! AAARRGGHHH!即使是发送大小,这种级别的完整性检查在Unix或INET套接字上完全是多余的。

我会挖掘更多,但这会浪费时间来理解这个C代码。使用网络嗅探器来计算出真正发生的事情;不要将此C代码用作如何编写自己的客户端的任何模型。