【问题标题】:Socket php server not showing messages sent from android clientSocket php服务器不显示从android客户端发送的消息
【发布时间】:2012-06-27 12:06:09
【问题描述】:

嗨,我是这类东西的新手,但这就是我想做的事情。

我正在尝试实现一个聊天应用程序,其中用户将从网站发送他们的查询,并且一旦网站用户发送消息。它将出现在网站所有者的 android 移动应用程序中,他们将回答他们查询。简而言之,我想实现实时聊天。

现在我只是简单地尝试将消息从 android 应用程序发送到 php 服务器。 但是当我在 chrome 中从 dreamweaver 运行我的 php 脚本时,浏览器会继续加载,并且在我从客户端发送消息时不显示任何输出。

有时,php 脚本会显示一些我从 android(客户端)发送的输出。但我不知道它何时有效,何时无效。

所以我想在我从客户端发送这些消息后立即在 php 脚本中显示这些消息,反之亦然(没有为客户端实现反之亦然,但我们将不胜感激)。

这是我到目前为止所做的。

php 脚本:

 <?php

 set_time_limit (0);
 $address = '127.0.0.1';

 $port = 1234;

 $sock = socket_create(AF_INET, SOCK_STREAM, 0);
 socket_bind($sock, $address, $port) or die('Could not bind to address');
 socket_listen($sock);


 $client = socket_accept($sock);
 $welcome = "Roll up, roll up, to the greatest show on earth!\n? ";
 socket_write($client, $welcome,strlen($welcome)) or die("Could not send connect string\n");

do{
$input=socket_read($client,1024,1) or die("Could not read input\n");
echo "User Says:  \n\t\t\t".$input;

if (trim($input) != "")
    { 
    echo "Received input: $input\n";
    if(trim($input)=="END")
    {
        socket_close($spawn);
        break;
    }
}
else{

$output = strrev($input) . "\n"; 
socket_write($spawn, $output . "? ", strlen (($output)+2)) or die("Could not write output\n");              
echo "Sent output: " . trim($output) . "\n";

}
}
while(true);


socket_close($sock);
echo "Socket Terminated";
?>

安卓代码:

  public class ServerClientActivity extends Activity {
   private Button bt;
   private TextView tv;
   private Socket socket;
   private String serverIpAddress = "127.0.0.1";

   private static final int REDIRECTED_SERVERPORT = 1234;

   @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    bt = (Button) findViewById(R.id.myButton);
    tv = (TextView) findViewById(R.id.myTextView);

    try
    {
        InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
        socket = new Socket(serverAddr, REDIRECTED_SERVERPORT);
    } 
    catch (UnknownHostException e1) 
    {
        e1.printStackTrace();
    }
    catch (IOException e1)
    {
        e1.printStackTrace();
    }


    bt.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
           try
           {
              EditText et = (EditText) findViewById(R.id.EditText01);
              String str = et.getText().toString();
              PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
              out.println(str);
              Log.d("Client", "Client sent message");
           }
           catch (UnknownHostException e)
           {
              tv.setText(e.getMessage());
              e.printStackTrace();
           }
           catch (IOException e) 
           {
              tv.setText(e.getMessage());
              e.printStackTrace();
           }
           catch (Exception e) 
           {
              tv.setText(e.getMessage());
              e.printStackTrace();
           }
        }

     });       

   }
 }

我刚刚粘贴了 Android 的 onclick 按钮事件代码。编辑文本是我要输入文本的文本框。 ip地址和端口与php脚本中的相同。

【问题讨论】:

标签: php android sockets


【解决方案1】:

您的地址 127.0.0.1 将解析为运行代码的机器。所以应用程序实际上会尝试连接到自身。在 MSDOS 控制台上键入 ipconfig /all 并改用该地址。

【讨论】:

    【解决方案2】:

    我建议使用事件驱动框架来处理您的连接。

    有一个相当不错的示例,名为 React,但其中包含大量其他内容,您可能需要去掉它,这样您的应用就不会依赖数百个外部组件。

    React 使用基于 libevent 的消息循环,如果你安装了它,或者 stream_select 否则。

    您使用闭包处理事件,例如:

        $client->on('read', function($data) use ($client) {
            $client->onRead($data);
        });
    

    这样,您将能够处理大量同时连接,并且不会占用您所有的 CPU。

    您的代码将在发生某事时执行。

    如果不出意外,看看它是如何工作的,你会更好地理解如何创建一个非阻塞事件驱动的套接字服务器。

    【讨论】:

      【解决方案3】:

      您是否尝试在发送到服务器之前将 '\r\n' 添加到 EditText 的值中?我认为问题不在于客户端和服务器之间的连接,因为连接失败时它不会显示错误。
      也许在您的情况下 socket_read($client,1024,1) 必须在 '\r\n' 处停止读取。

      更新:您的本地 ip 可能会导致连接错误。看看this link

      【讨论】:

      • @Mj1992:我已经更新了我的答案。您应该在连接失败时写入日志并使用 logcat 更新您的问题,尤其是在 android 端创建新套接字时。
      【解决方案4】:

      首先 - 您的服务器一次只能处理一个客户端连接,这对聊天没有意义。

      我看不到您如何处理 Android 端的套接字连接,但无论如何,只要您的脚本执行不会执行“socket_accept()”并等待,它就不会允许您再次连接用于连接。

      您应该运行 1 个循环进程来获取新的客户端连接并将每个连接的客户端分叉到单独的进程中。

      看看我在这里编写的同一个轻量级 PHP 服务器,它基于相同的原理: https://github.com/webdevbyjoss/Aaaaa---space-ships-combat-multiplayer-game/blob/master/server/server.php

      忽略与 Websocket 相关的“doHandshake()”和“WebSocketFrame::decode/WebSocketFrame::encode”,但其余的应该没问题。

      通常它运行循环

      while (true) 
      
          if (($msgsock = socket_accept ( $sock )) === false) {
              echo "socket_accept() failed: reason: " . socket_strerror ( socket_last_error ( $sock ) ) . "\n";
          break;
          }
      
          // We got a client connected, lets process it in separate thread
          if (($pid = pcntl_fork()) === -1) {
              echo "pcntl_fork() failed. Make sure you are on Linux sustem, but not on Windows\n";
              break;
          }
      
          if (!$pid) { // client
              handleClient($msgsock);
              exit();
          }
      
          // parent server will wait to accept more clients connections in new loop
      }
      

      handleClient() 函数中,您应该有一个单独的循环来与客户端通信。

      while (true) {
          if (false === ($buf = socket_read ( $msgsock, 2048, PHP_BINARY_READ ))) {
              echo "socket_read() failed: reason: " . socket_strerror ( socket_last_error ( $msgsock ) ) . "\n";
              return;
          }
      
          if (empty($buf)) { // do disconnection check
              echo "Client disconnected\n";
              return;
          }
      
         // -------------------------------------------------------------
         // PUT YOUR BUSINESS LOGIC HERE
         // TO HANDLE MESSAGES OF THE CHAT AND GENERATE RESPONSE TO USER
         // I RECOMMEND TO USE SOMETHING LIKE MEMCACHE/REDIS/MONGO/MYSQL/TXT-FILES
         // FOR MULTIPROCESS DATA INTERCHANGE
         // -------------------------------------------------------------
      
      // transfer data to client
          socket_write($msgsock, $returnText, strlen($returnFrame));
      }
      
      socket_close ( $msgsock );
      

      【讨论】:

      • thnx 我正在使用 Windows 的回复。那么这对您在必须使用 linux 的代码中编写的有什么影响吗?
      • 出现同样的问题,页面一直在加载,当我从 android 客户端发送消息时,它什么也没做,只是一直在加载页面。我已经更新了 android 代码。
      • stream_select > pcntl_fork。是时候学习一些事件驱动编程了。
      • 是的,值得研究 PHP 中的事件驱动编程,感谢您的指出!
      • 您能详细解释一下这种情况下的事件驱动编程吗?
      猜你喜欢
      • 1970-01-01
      • 2013-11-10
      • 2015-04-25
      • 2020-09-06
      • 1970-01-01
      • 2013-04-24
      • 2017-01-12
      • 2023-04-03
      • 1970-01-01
      相关资源
      最近更新 更多