嗨,我是这类东西的新手,但这就是我想做的事。
我正在尝试实现一个聊天应用程序,用户将从网站发送他们的查询,并且一旦网站用户发送消息。它将出现在网站所有者的Android移动应用程序中,他们将回答他们的问题查询。简而言之,我想实现一个实时聊天。
现在我只是想简单地尝试从Android应用程序发送消息到php服务器。 但是当我从chromeweaver中运行我的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";
?>
Android代码:
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.Edit的onclick按钮事件代码文本是我要输入文本的文本框。 ip地址和端口与php脚本相同。
答案 0 :(得分:1)
首先 - 您的服务器一次只能处理一个客户端连接,这对聊天没有意义。
我无法看到你如何处理Android端的套接字连接,但无论如何,只要你的脚本执行不执行“ socket_accept()”并等待,它就不允许你再次连接用于连接。
您应该运行1个循环过程来获取新的客户端连接,并将每个连接的客户端分成单独的进程。
看一下我在这里写的基于相同原理的轻量级PHP服务器: https://github.com/webdevbyjoss/Aaaaa---space-ships-combat-multiplayer-game/blob/master/server/server.php
忽略与“ doHandshake()”和“ WebSocketFrame :: decode / WebSocketFrame :: encode ”相关的Websockets,但其他人应该没问题。
通常它会运行循环
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 );
答案 1 :(得分:1)
我建议使用事件驱动的框架来处理您的连接。
有一个相当不错的例子称为React,但它有很多其他东西,你可能想要剥离,所以你的应用程序不依赖于数百个外部组件。
如果安装了libevent
,则React会使用基于stream_select
的消息循环,否则会使用 $client->on('read', function($data) use ($client) {
$client->onRead($data);
});
。
您使用闭包处理事件,例如:
{{1}}
通过这种方式,您将能够处理大量的并发连接,并且不会占用您的所有CPU。
当发生某些事情时,您的代码将会执行。
如果没有别的,看看它是如何工作的,你将更好地理解如何创建一个非阻塞事件驱动的套接字服务器。
答案 2 :(得分:0)
您是否尝试在发送到服务器之前将'\ r \ n'添加到EditText的值中?我认为问题不是客户端和服务器之间的连接,因为它在连接失败时不显示错误。
也许在你的情况下 socket_read($ client,1024,1)必须停止阅读'\ r \ n'。
更新:您的本地IP可能会导致连接错误。看看this link
答案 3 :(得分:0)
您的地址127.0.0.1将解析为运行代码的计算机。所以应用程序实际上试图连接到自己。在MSDOS控制台上键入ipconfig /all
并改为使用该地址。