chat.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. <?php
  2. /**
  3. * TCP Client DEMO
  4. */
  5. define('CONFIG_FILE', __DIR__ . '/../config.php');
  6. include __DIR__ . '/../lib/functions.php';
  7. include __DIR__ . '/../lib/message.php';
  8. if ($argc < 2) {
  9. die("Usage: {$argv[0]} <name> <input file>\n");
  10. }
  11. if ($argc > 2) {
  12. if (!file_exists($argv[2])) {
  13. die("file {$argv[2]} is not exists!\n");
  14. }
  15. $intype = filetype($argv[2]);
  16. if (!in_array($intype, ['fifo', 'file'])) {
  17. die("file {$argv[2]} is not a fifo file or a regular file!\n");
  18. }
  19. $infile = fopen($argv[2], 'r+');
  20. if (!$infile) {
  21. die("open file {$argv[2]} failed!\n");
  22. }
  23. } else {
  24. $intype = 'stdin';
  25. $infile = STDIN;
  26. }
  27. $cfg = [];
  28. load_config();
  29. $myid = 0;
  30. $users = [];
  31. //创建TCP连接
  32. $c = stream_socket_client("tcp://{$cfg['host']}:{$cfg['port']}", $errno, $error);
  33. if (!$c) {
  34. die("#{$errno}: {$error}\n");
  35. }
  36. //发送登录请求
  37. $msg = new Message();
  38. $msg->set('cmd', 'login');
  39. $msg->set('name', $argv[1]);
  40. fwrite($c, $msg->toBuffer());
  41. //循环接收来自标准输入和服务器端的数据
  42. $buffer = '';
  43. while (1) {
  44. if (feof($infile)) {
  45. if ($intype == 'stdin') {
  46. break;
  47. } else {
  48. fclose($infile);
  49. $intype = 'stdin';
  50. $infile = STDIN;
  51. }
  52. }
  53. $rlist = [$infile, $c];
  54. $wlist = [];
  55. $elist = [];
  56. if (!stream_select($rlist, $wlist, $elist, NULL)) {
  57. break;
  58. }
  59. foreach ($rlist as $fd) {
  60. if ($fd == $infile) {
  61. $line = trim(fgets($infile));
  62. if (empty($line)) {
  63. continue;
  64. }
  65. $data = json_decode($line, true);
  66. if ($data) {
  67. $msg = new Message();
  68. foreach ($data as $k => $v) {
  69. $msg->set($k, $v);
  70. }
  71. fwrite($c, $msg->toBuffer());
  72. } else {
  73. echo "输入的内容不是JSON格式的:{$line}\n";
  74. }
  75. } elseif ($fd == $c) {
  76. $readbuff = fread($c, 1024);
  77. if (empty($readbuff)) { //接收消息失败
  78. echo "网络断开……\n";
  79. break 2;
  80. } else { //成功接收到消息
  81. $buffer .= $readbuff;
  82. while (1) {
  83. $msg = Message::parse($buffer);
  84. if ($msg) {
  85. onMessage($msg);
  86. } else {
  87. break 2;
  88. }
  89. }
  90. }
  91. }
  92. }
  93. }
  94. fclose($c);
  95. fclose($infile);
  96. //服务端返回结果的处理
  97. function onMessage($msg)
  98. {
  99. global $myid, $users;
  100. $cmd = $msg->get('cmd');
  101. $id = $msg->get('id');
  102. $name = $msg->get('name');
  103. //根据不同的命令进行对应的处理
  104. switch ($cmd) {
  105. //登录成功
  106. case 'login':
  107. $myid = $id;
  108. $users = $msg->get('data');
  109. echo "当前用户列表:\n";
  110. foreach ($users as $id => $name) {
  111. echo "\t#{$id} => {$name}\n";
  112. }
  113. break;
  114. //用户上线
  115. case 'enter':
  116. echo "[#{$id} {$name}]上线了\n";
  117. $users[$id] = $name;
  118. break;
  119. //用户下线
  120. case 'leave':
  121. echo "[#{$id} {$name}]已下线\n";
  122. break;
  123. //广播
  124. case 'bc':
  125. $data = $msg->get('data');
  126. echo "[#{$id} {$name}]广播:{$data}\n";
  127. break;
  128. //私信
  129. case 'talk':
  130. $to = $msg->get('to');
  131. $data = $msg->get('data');
  132. if ($to == $myid) {
  133. echo "#{$id} {$name}对您说:{$data}\n";
  134. } else {
  135. echo "您对 #{$to} {$users[$to]} 说:{$data}\n";
  136. }
  137. break;
  138. }
  139. }