笔者读了TCP/IP协议栈的相关程序,在HTTP层有一段程序没读懂,一条语句是“memcpy(conxn[nr].query, tcp_data, 20);         //将20个字节拷贝到缓存,”“query代表什么?“20”代表什么?为什么不是30或者更多?”以下是包括了这条语句的部分源程序。
 

UINT http_server(UCHAR xdata * inbuf, UINT header_len, UCHAR nr, UCHAR resend)
{
 UCHAR i;
 UINT idata body_len, hhdr_len, jhdr_len, page_len, jpeg_len;
 UINT idata sent, remaining;
 UCHAR xdata * outbuf;
 UCHAR xdata * ptr;
 UCHAR xdata * tcp_data;
 UCHAR idata request;
   static UCHAR idata post_flg = FALSE;
       
 // Make sure this is a valid connection
 if (nr == NO_CONNECTION) return 0;         //无连接,则返回
 
 // Compute start of TCP data
  
   // Save first 20 chars and seq number just in case
   // we need to re-generate page
   // TODO: if post, then save switch state infomation
  
   if (!resend)              
   {
   //如果当前不是出于重发状态,那么将tcp_data定位到inbuf的特定位置(IP+以太网首部+TCP首部,三个偏移量)                 //
      tcp_data = inbuf + 34 + header_len;        
      memcpy(conxn[nr].query, tcp_data, 20);         //将20个字节拷贝到缓存
      conxn[nr].old_sequence = conxn[nr].my_sequence;       //更新old_sequence字段
   }
   // If this is a resend, set sequence number to what it was
   // the last time we sent this
   else
   {
      tcp_data = inbuf;
      conxn[nr].my_sequence = conxn[nr].old_sequence;  
   }
  
   // Start off with no request
   request = NONE;                //此时没有请求
     
 // TODO: Calling strstr() on a large buffer takes a lot of time
   // so perhaps we could speed things up by limiting the search
   // range to the portion of the buffer where the item is expected
   // to be found
 
 // If it is a POST, then set a flag to start looking for the post
 // data of interest, which is the string "switch=".  It may arrive
 // in a later segment (Netscape seems to split up the POST message)
   if (strstr(tcp_data, "POST") != NULL) post_flg = TRUE;       //如果TCP数据段里含有post,将post标志位置位
   
   // See if this is a GET message
   else if (strstr(tcp_data, "GET") != NULL)         //如果客户端向服务器索取资源
   {
      post_flg = FALSE;               //屏蔽资源索取标志位
      if (strstr(tcp_data, "photo1") != NULL) request = GET_JPEG;    //获取图片
      else if (strstr(tcp_data, "index") != NULL) request = GET_PAGE;
      else if (strstr(tcp_data, "/ ") != NULL) request = GET_PAGE;    //获取页面
   }
  
   // If POST flag is "armed" then look for the "switch=" string
   // and if found, turn the LED on or off according to whether
   // the browser is sending a 1 or a 0.
   if (post_flg)
   {
      ptr = strstr(tcp_data, "switch=");
      if (ptr != NULL)             
      {
         // Move to space after equals sign
         // Set control indicator accordingly
         post_flg = FALSE;
         request = POST_PAGE;           //响应类型为POST_PAGE
         ptr += 7;
         if (*ptr == '1') {CONTROL_LED=0x0;}  
         else if (*ptr == '0') {CONTROL_LED=0x1;}      //查看"亮"这一字段 ,返回LED的控制符号
   LightONOFF(CONTROL_LED);
   //P36=CONTROL_LED;
   }
   }

   if ((request == GET_PAGE) || (request == POST_PAGE))
   {
      // Figure out sizes           
      hhdr_len = strlen(html_header);         //html首部长度
      page_len = strlen(web_page);          //html页面长度
      body_len = hhdr_len + page_len;         //页面长度+数据段长度=整体长度
     
      // Free memory holding received message.  The message from the
      // browser can be 500+ bytes long so this is a significant
      // chunk out of the available malloc space of 1500 bytes
      if (!resend) { rcve_buf_allocated = FALSE;}      //如果不是第二次发送,清输入缓冲 ,缓冲区占用标志位清0

      // Allocate memory for entire outgoing message including
      // 14 byte Ethernet + 20 byte IP + 20 byte TCP headers
      // Allow 1 byte for NULL char at the end
     // outbuf = (UCHAR xdata *)malloc(54 + body_len + 1);
     // if (outbuf == NULL)
      //{
        // return 0;
      //}
      outbuf = outbuf1;              //为整个输出缓冲区开辟空间
      // Copy page data.  This moves data from flash into RAM.  It is
      // an undesirable process, but must get data into RAM to replace
      // tags
  memcpy(outbuf + 54, html_header, hhdr_len);
  memcpy(outbuf + 54 + hhdr_len, web_page, page_len);
            
    outbuf[54 + body_len] = 0;  // Append NULL
  
      // Replace length tag with actual value
      itoa(page_len, text, 10);
  replace_tag(outbuf + 54, "TAG:LEN1", text);
  
  // Replace CPU temperature tag with actual value
  itoa(cpu_temperature/100, text, 10);
  i=strlen(text);
  text[i]='.';
  i++;
  itoa(cpu_temperature%100, text+i, 10);
  replace_tag(outbuf + 54, "TAG:TMP1", text);

  itoa(air_temperature/1000, text, 10);
  i=strlen(text);
  text[i]='.';
  i++;
  itoa(air_temperature%1000, text+i, 10);
  replace_tag(outbuf + 54, "TAG:TMP2", text);

  // Replace CPU voltage tag with actual value X 100
  // Insert decimal point between first and second digits
  itoa(cpu_voltage/1000, text, 10);
  i=strlen(text);
  text[i]='.';
  i++;
  itoa(cpu_voltage%1000, text+i, 10);
  replace_tag(outbuf + 54, "TAG:VOL1", text);
     
      // Insert the word CHECKED into the html so the browser will
  // check the correct LED state indicator box
      if (CONTROL_LED == OFF) replace_tag(outbuf + 54, "TAG:CHK1", "CHECKED");
      else replace_tag(outbuf + 54, "TAG:CHK2", "CHECKED");
     
      // Segment length = body_len + 20
      http_send(outbuf, body_len + 20, nr);
      conxn[nr].my_sequence += body_len;
   }
   else if (request == GET_JPEG)
   {
      // Ths browser has requested the jpeg p_w_picpath.  First figure out
      // sizes - cannot use sizeof() for jpeg here because it is in
      // another module.  Just directly specify length of it
      jhdr_len = strlen(jpeg_header);
      jpeg_len = 5705;//6194;
      body_len = jhdr_len + jpeg_len;
     
      // Free memory holding received message.  The message from the
      // browser can be 500+ bytes long so this is a significant
      // chunk out of the available malloc space of 1500 bytes
      if (!resend) { rcve_buf_allocated = FALSE;}

      // First send the header and enough of the jpeg to make 1000 bytes.
      // The value of 1000 is arbitrary, but must be stay under 1500.
      if (body_len < 1000) remaining = body_len; else remaining = 1000;
//      outbuf = (UCHAR xdata *)malloc(54 + remaining + 1);
      //if (outbuf == NULL)
      //{
        // return 0;
      //}
      outbuf=outbuf1;
      memcpy(outbuf + 54, jpeg_header, jhdr_len);
  memcpy(outbuf + 54 + jhdr_len, photo1_jpeg, remaining - jhdr_len);
                 
      outbuf[54 + remaining] = 0;  // Append NULL

      // Replace jpeg length tag with actual value
      itoa(jpeg_len, text, 10);
  replace_tag(outbuf + 54, "TAG:LEN2", text);

      http_send(outbuf, remaining + 20, nr);
      sent = remaining - jhdr_len;
      conxn[nr].my_sequence += remaining;
    
      // Send the rest of the jpeg file in 1000 byte chunks.  This sends about
      // 6 segments of 1000 bytes back to back, but we should actually process
      // acks from the other end to make sure we are not sending more than the
      // other end can receive.  Most systems can handle 6K
      while (sent < jpeg_len)
      {
         remaining = jpeg_len - sent;
         if (remaining > 1000) remaining = 1000;
        //  outbuf = (UCHAR xdata *)malloc(54 + remaining + 1);
         outbuf=outbuf1;
  // if (outbuf == NULL)
         //{
          //  return 0;
         //}
        
         memcpy(outbuf + 54, photo1_jpeg + sent, remaining);
                          
         outbuf[54 + remaining] = 0;  // Append NULL
         http_send(outbuf, remaining + 20, nr);
         sent += remaining;
         conxn[nr].my_sequence += remaining;
      }
   }
   else
   {
      // The incoming HTTP message did not warrant a response
      return 0;
   }
  
   // Return number of bytes sent, not including TCP header
 return(body_len);
}