'Based on HTTP long connection'; 'Server push'; Technical PHP simple chat room

  • 2020-03-31 16:46:01
  • OfStack

The first is the home page, which contains a text entry and an iframe to show the chat, and a hidden iframe to submit the form:
 
<?php 
//chat.php 
header('cache-control: private'); 
header('Content-Type: text/html; charset=utf-8'); 
?> 
<html> 
<script type="text/javascript"> 
function submitChat(obj) { 
obj.submit(); 
document.getElementsByName('content')[0].value = ''; 
} 
</script> 
<iframe src="./chat_content.php" height="300" width="100%"></iframe> 
<iframe name="say" height="0" width="0"></iframe> 
<form method="POST" target="say" action="./say.php" onsubmit="submitChat(this)"> 
<input type="text" size="30" name="content" /> <input type="button" value="say" onclick="submitChat(this.form)" /> 
</form> 
</html> 

The other is to save the chat content submitted by the user. I simply wrote the text, and did not do any locking, this is just a simple version:
 
<?php 
$content = trim($_POST['content']); 
if ($content) { 
$fp = fopen('./chat.txt', 'a'); 
fwrite($fp, $content . "n"); 
fclose($fp); 
clearstatcache(); 
} 
?> 

Next, look at the main HTTP long connection section, the chat_content.php file:
 
<?php 
header('cache-control: private'); 
header('Content-Type: text/html; charset=utf-8'); 
//The test is set to timeout 30 seconds, which is usually set for a long time.
set_time_limit(30); 
//This row is just to figure out what IE is, what BT is
echo str_repeat(' ', 256); 
ob_flush(); 
flush(); 
$fp = new SplFileObject('./chat.txt', 'r+'); 
$line = 0; 
$totalLine = 0; 
while (!$fp->eof()) { 
$fp->current(); 
$totalLine++; 
$fp->next(); 
} 
$fp->seek($totalLine); 
$i = $totalLine - 1; 
while (true) { 
if (!$fp->eof()) { 
if ($content = trim($fp->current())) { 
echo '<div>'; 
echo htmlspecialchars($content); 
echo "</div>"; 
flush(); 
$fp->next(); 
$i++; 
} 
} else { 
$fp->seek($i - 1); 
$fp->next(); 
} 
{ 
//Here you can add heartbeat detection and exit the loop
} 
usleep(1000); 
} 
?> 

Let me explain it line by line, which is actually easier to understand:
06. Set a timeout time, which must be a few hours to maintain a long HTTP connection. As mentioned in the article above, this type of HTTP connection can only be opened two times due to browser limitations. In addition, even if you set a never timeout, the configuration file on the server (such as Apache) may set the maximum waiting time for HTTP requests, so the effect may not be what you think, and the default may be a 15-minute timeout. If you are interested, you can try to modify it yourself.
09. Here is the output for a blank, the main is showing on the manual, IE browser output is not directly in front of 256 characters, so we'll just output some blank, in order to let the content behind the output, may be other browsers have other browser Settings, specific can see the PHP manual frush function description. The next 11 or 12 lines force the white space to be thrown to the browser output.
13. ~ 20. The main purpose here is to count the number of lines in the file so that you can start reading after that line.
If a user writes to a file, the current detection is definitely not the end of the file, then the line is read out and output. Otherwise, move the pointer forward one line, continue the loop, and wait for 1000 microseconds at a time.
39. If keep long connection, so even if the client disconnects, the service side is also not necessarily know that the client has been disconnected, so there may need to do some heartbeat records, such as each user to keep a heartbeat flag, each update last heartbeat a few seconds, when the test last time after a long time didn't update, out of the infinite loop, close the HTTP connection.
OK, the basic principle is like this, of course this performance is not clear, interested in their own try, welcome to communicate.

Related articles: