2012-06-26 154 views
2

嗨,我是这些类型的新手,但这是我想要做的。套接字PHP服务器不显示从Android客户端发送的消息

我试图实现一个聊天应用程序,用户将从网站发送他们的查询,并且一旦这些消息被网站用户发送,它就会出现在网站所有者的android手机应用程序中,他们会回答他们的疑问。简而言之,我想实施一个实时聊天。

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

有时候会发生这样的情况,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

这可能有点偏离主题,您可以在我的上一篇文章中获得一些灵感和有用的建议。 https://stackoverflow.com/questions/29159354/php-socket-with-android/45851814#45851814 这里是一些非常有用的代码,可以帮助你下载。 http://developersfound.com/PHP_SocketServer_Android_SocketClient.zip – user2288580

回答

1

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

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

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

您处理与倒闭事件,像:

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

有了这个,你将能够处理大量的并发连接,而​​且它不会占用你所有的CPU。

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

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

1

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

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

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

采取看看我写到这里我一样的轻量级PHP服务器是基于同样的原则: https://github.com/webdevbyjoss/Aaaaa---space-ships-combat-multiplayer-game/blob/master/server/server.php

忽略相关的WebSockets “doHandshake()” 和“WebSocketFrame ::解码/ WebSocketFrame: :编码“但你应该没问题。

一般来说,运行循环

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); 
+0

thnx的答复我使用Windows.So是否有任何区别,因为你写的代码必须使用Linux? – Mj1992

+0

同样的问题是发生页面不断加载,当我从android客户端发送消息它不会做任何事情只是不断加载页面。我已更新android代码。 – Mj1992

+1

'stream_select'>'pcntl_fork'。有时间学习一些事件驱动的编程。 – Leigh

0

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

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

+0

不起作用:) – Mj1992

+0

@ Mj1992:我已经更新了我的答案。你应该在连接失败时写日志,并用logcat更新你的问题,特别是在android端创建新套接字时。 – R4j

0

您的地址127.0.0.1将解析为代码运行的机器。所以应用程序实际上试图连接到它自己。请在MSDOS控制台上键入ipconfig /all,然后改为使用该地址。

相关问题