2012-06-26 2 views
2

안녕하세요 저는 이런 종류의 초보자입니다.하지만 여기에 내가하고 싶은 것이 있습니다.소켓 PHP 서버가 안드로이드 클라이언트에서 보낸 메시지를 표시하지 않습니다.

사용자가 웹 사이트에서 질문을 보내고 웹 사이트 사용자가 메시지를 보내면 채팅 응용 프로그램을 구현하려고합니다. 사이트 소유자의 안드로이드 모바일 응용 프로그램에 응답합니다 간단히 말해서 나는 라이브 채팅을 구현하고 싶다.

지금 당장 나는 단지 안드로이드 애플 리케이션에서 PHP 서버로 메시지를 보내려고합니다. 그러나 dreamweaver에서 PHP 스크립트를 실행하면 브라우저가 계속로드되며 클라이언트에서 메시지를 보낼 때 출력이 표시되지 않습니다.

가끔은 PHP 스크립트가 내가 안드로이드 (클라이언트)에서 보낸 몇 가지 출력을 보여줬는데.하지만 작동하지 않을 때와 때를 모르겠습니다.

그래서 클라이언트에서 메시지를 보내 자마자 그 메시지를 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.Edit 텍스트의 온 클릭 버튼 이벤트 코드를 붙여 넣은 내가 내 텍스트를 입력하기 위하여려고하고 텍스트 상자입니다 . 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

먼저 서버가 클라이언트 연결 한 번만 처리하므로 채팅에는 적합하지 않습니다.

안드로이드 측에서는 소켓 연결을 어떻게 처리하는지 알 수 없지만 스크립트 실행이 "socket_accept()"을 실행하지 않고 연결을 기다리지 않는 한 다시 연결할 수 없습니다.

새 클라이언트 연결을 잡고 각 연결된 클라이언트에 별도의 프로세스로 포크하려면 1 루프 프로세스를 실행해야합니다. 같은 원리를 기반으로 내가 여기에 쓴 내 같은 경량 PHP 서버에서

테이크 모양 : https://github.com/webdevbyjoss/Aaaaa---space-ships-combat-multiplayer-game/blob/master/server/server.php

관련 WebSocket을 무시 "doHandshake()"와 "WebSocketFrame :: 디코딩/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); 
+0

회신을 위해 thnx 나는 Windows.So를 사용하고 있는데 리눅스를 사용해야하는 코드에 작성한대로 차이가 있습니까? – Mj1992

+0

동일한 문제가 페이지로드 중 계속 발생하며, 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으로 질문을 업데이트해야합니다. 특히 안드로이드 측에서 새 소켓을 만들 때 더욱 그렇습니다. – R4j

0

주소 127.0.0.1은 코드가 실행되는 컴퓨터로 확인됩니다. 따라서 앱은 실제로 자체 연결을 시도합니다. MSDOS 콘솔에 ipconfig /all을 입력하고 해당 주소를 대신 사용하십시오.

관련 문제