3

我正在尝试与服务器通信。但我似乎无法让它在我的手机上接收来自服务器的响应。它只是挂在一个无限循环中。它在 python 客户端中接收,但在 java 客户端中没有。有什么我做错了吗?

服务器:

"""
TODO:
Save password to file
Add password change feature
some sort of garage open/close sensor?
"""
#import RPi.GPIO as GPIO
import SocketServer
import time

#GPIO.setmode(GPIO.BOARD)
#GPIO.setup(12,GPIO.OUT)
auth = ""#Syntax: password-port
#auth = "o-1234" #Debug
global isOpen
class TCPConnectionHandler(SocketServer.BaseRequestHandler):
    """
    The RequestHandler class for our server.

    It is instantiated once per connection to the server, and must
    override the handle() method to implement communication to the
    client.
    """
    global isOpen #global is kinda like public in java


    def handle(self):
        isOpen = False
        while 1:
            self.data = self.request.recv(1024).strip()
            print self.data
            if self.data == '':#client ended stream
                break
            elif (self.data == auth.split('-')[0]):#if self.data matches the password
                isOpen = (not isOpen)#change garage status
                print isOpen
                self.request.sendall('got_it')#dont leave the client hanging, let it know whats up
#               GPIO.output(12,1)
#               time.sleep(0.5)#simulate button press
#               GPIO.output(12,0)
            elif (self.data == 'req_state'):#sends back the current state of the garage
                print isOpen
                self.request.sendall(str(isOpen))

            else:
                print 'wat?'
                self.request.sendall('wat')
        self.request.close()    

class Server(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    # Ctrl-C will cleanly kill all spawned threads
    daemon_threads = True
    # much faster rebinding
    allow_reuse_address = True

    def __init__(self, server_address, RequestHandlerClass):
        SocketServer.TCPServer.__init__(\
        self,\
        server_address,\
        RequestHandlerClass)

if __name__ == "__main__":

    HOST, PORT = "", int(auth.split('-')[1])#blank means localhost
    print "Server started on " + HOST + ":"+ str(PORT)
    server = Server((HOST, PORT), TCPConnectionHandler)

    # Activate the server; this will keep running until you
    # interrupt the program with Ctrl-C
    server.serve_forever()

安卓客户端:

package com.Civilizedgravy.madgarage;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.util.Log;

public class Socketstuff extends AsyncTask<String, String, String> {

    @Override
    protected void onProgressUpdate(String... values) {
        // TODO Auto-generated method stub
        super.onProgressUpdate(values);
        ma.dbg.setText(values[0]);
    }

    public boolean connected;
    private final int PORT = 1234;
    private String HOMEIP = "0.0.0.0";
    private String pass;
    public MainActivity ma;

    public Socketstuff(MainActivity ma) {
        this.ma = ma;
    }

    @Override
    protected String doInBackground(String... params) {
        publishProgress("");
        SharedPreferences sharedPref = PreferenceManager
                .getDefaultSharedPreferences(ma);
        HOMEIP = sharedPref.getString("pref_ip", "0.0.0.0");
        pass = sharedPref.getString("pref_Passkey", "o-1234");
        // TODO Auto-generated
        Log.d("MadG",
                HOMEIP + ", " + pass + ", "
                        + String.valueOf(pass.split("-").length));
        if (pass.split("-").length <= 2) {

            try {
                InetAddress serverAddr = InetAddress.getByName(HOMEIP);
                Log.d("ClientActivity", "C: Connecting...");
                Socket socket = new Socket(serverAddr, Integer.parseInt(pass
                        .split("-")[1]));

                try {
                    Log.d("ClientActivity", "C: Sending command.");
                    PrintWriter out = new PrintWriter(new BufferedWriter(
                            new OutputStreamWriter(socket.getOutputStream())),
                            true);
                    if (params[0].equals("o")) {
                        out.println(pass.split("-")[0]);
                        Log.d("MadG", "Open");
                    } else {
                        Log.d("ClientActivity", "Requesting state.");
                        out.println("req_state");
                        Log.d("MadG", "Waiting for response...");
                        String resp = StreamToString(socket.getInputStream());//hangs here
                        Log.d("MadG", "Got response:" + resp);
                        publishProgress(resp);

                    }

                    Log.d("ClientActivity", "C: Sent.");

                    out.println("\n");
                } catch (Exception e) {
                    publishProgress("ERROR: unable to send command");
                    Log.e("ClientActivity", "S: Error", e);
                }
                socket.close();
                Log.d("ClientActivity", "C: Closed.");
            } catch (Exception e) {
                publishProgress("ERROR: unable to connect");
                Log.e("ClientActivity", "C: Error", e);
                connected = false;
            }
        }
        return HOMEIP;

    }
    public static String StreamToString(InputStream is) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;

        while ((line = reader.readLine()) != null) {
            Log.d("MadG", sb.toString());
            sb.append(line);
        }

        is.close();

        return sb.toString();
    }
}
4

2 回答 2

1

我发现了问题。它挂起的原因是因为 readLine() 正在等待接收 '\n' 字符,所以我将服务器更改为在响应结束时发送 '\n'

self.request.sendall('wat' + '\n')
于 2013-08-06T04:49:41.020 回答
1

最后一行是否有退货?如果没有, readLine() 将挂起,直到发送返回。此外,如果您使用的是 HTTP 1.1,则连接可能会保持打开状态并等待响应。确保您的 Content-Length 标头也正确。

于 2013-08-05T22:03:00.520 回答