套接字 php 服务器不显示从安卓客户端发送的消息


Socket php server not showing messages sent from android client

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

我正在尝试实现一个聊天应用程序,用户将在网站用户发送消息后立即从网站发送查询。它将出现在网站所有者的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的点击按钮事件代码.编辑文本是我要输入文本的文本框。IP 地址和端口与 php 脚本相同。

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

有一个相当不错的例子叫做 React,但它里面有很多其他的东西,你可能想要去掉,这样你的应用程序就不会依赖于数百个外部组件。

React 使用基于 libevent 的消息循环(如果您已安装它),否则stream_select

您可以使用闭包处理事件,如下所示:

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

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

当发生某些事情,您的代码将被执行。

如果没有别的,看看它是如何工作的,你会更好地了解如何创建一个非阻塞事件驱动的套接字服务器。

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

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

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

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

忽略与 Websockets 相关的 "doHandshake()" 和 "WebSocketFrame::d ecode/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 );

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

更新:您的本地 IP 可能会导致连接错误。看看这个链接

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