【问题标题】:Getting body content sent using socket php using ports使用端口获取使用套接字 php 发送的正文内容
【发布时间】:2018-04-27 17:11:19
【问题描述】:

我有下面的代码,它接受使用套接字的连接并显示它,然后发回一些标头,但是我看不到已发送到侦听器的正文内容,我只得到代码下方所示的标头,带有Content-length 明确表示内容已发送,请帮忙

    $host = "192.168.8.121";
    $port = 454;

    // don't timeout!
    set_time_limit(0);

    // create socket
    $socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
    $result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");
    $result = socket_listen($socket, 3) or die("Could not set up socket listener\n");

    do {
       $spawn = socket_accept($socket) or die("Could not accept incoming connection\n");

    // read client input
       $input = socket_read($spawn, 1024) or die("Could not read input\n");

       $inputJSON = file_get_contents('php://input');
       $body = json_decode($inputJSON, TRUE); 
       print_r($input);
       print_r($body);
       print_r($inputJSON);

    // set inital headers
       $headers = [];
       $headers['Date'] = gmdate('D, d M Y H:i:s T');
       $headers['Content-Type'] = 'text/html; charset=utf-8';
       $headers['Server'] = $_SERVER['SERVER_NAME'];

       $lines = [];
       $lines[] = "HTTP/1.1 200 OK";

       // add the headers
       foreach ($headers as $key => $value) {
           $lines[] = $key . ": " . $value;
       }

       socket_write($spawn, implode("\r\n", $lines) . "\r\n\r\n" . $body) or die("Could not write output\n");
       socket_close($spawn);
    } while (true);

    // close sockets
    socket_close($socket);

我尝试了不同的方式来打印内容,但我只能打印出标题,这是我在打印 $input 变量时得到的

     POST /test HTTP/1.1 Accept: application/json, application/xml, 
     text/json, text/x-json, text/javascript, text/xml User-Agent: 
     RestSharp/105.2.3.0 Content-Type: application/json Host: 
     192.168.8.102:454 Content-Length: 779 Accept-Encoding: gzip, 
     deflate

【问题讨论】:

    标签: php sockets websocket port


    【解决方案1】:

    TCP 以数据包的形式发送数据并将它们重新组合成一个流。这意味着虽然您可以逐字节读取数据,而无需关心到达接收器的数据包的正确顺序,但仍然可能发生对socket_read() 的一次调用仅返回一个 IP 数据包的内容。发送者可能将标头作为一个数据包发送,然后将内容以一个或多个附加数据包的形式发送。

    通常的做法是在类似这样的循环中调用接收函数:

    $readTotal = 0;
    while ($readTotal < $toRead) {
      $read = socket_read(...);
      if ($read === FALSE) {
        // error, cancel operation
      }
      $readTotal += $read;
    }
    

    在您的情况下,您必须从 Content-Length 字段中提取要读取的数量,如果您无法读取标头中承诺的字节数,则可能会在循环中设置超时。

    【讨论】:

    • 嗨@Karsten,尝试实现这一点,但似乎无法做到正确,当我这样做时似乎耗尽了资源,因为服务器突然变得非常慢:-(
    猜你喜欢
    • 2012-05-21
    • 1970-01-01
    • 2020-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-30
    相关资源
    最近更新 更多