【问题标题】:Android Socket to Python Server - TimeoutAndroid Socket 到 Python 服务器 - 超时
【发布时间】:2014-07-24 01:10:04
【问题描述】:

我正在尝试编写一个将字符串发送到指定 IP 地址和端口号的应用程序。目的地已经有一个接受字符串的服务器,但由于某种原因,应用程序无法与服务器建立套接字,它一直超时。我只写过代码,所以如果我必须在客户端或服务器端做其他事情,比如端口转发,请告诉我。

这个应用程序的目标是接收一个字符串作为 IP 地址、一个字符串作为端口号,以及一个字符串作为要发送到目的地的消息的字符串。按下发送按钮后,应用程序会将消息发送到定义的 IP 和端口号,并显示来自服务器的响应。

这也将用于两个应用程序:一次在 Android 应用程序和 Python 服务器之间,另一次在 Android 应用程序和自定义硬件之间。希望有适合这两种情况的解决方案。

客户代码:

public static class PlaceholderFragment extends Fragment {

        TextView recieve;
        EditText addressText, portText, messageText;
        Button send;

        Socket socket = null;

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(
                    R.layout.fragment_customize_gateway, container, false);

            recieve = (TextView) rootView.findViewById(R.id.textView1);
            addressText = (EditText) rootView.findViewById(R.id.editText1);
            portText = (EditText) rootView.findViewById(R.id.editText2);
            messageText = (EditText) rootView.findViewById(R.id.editText3);

            send = (Button) rootView.findViewById(R.id.send);
            send.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    AsyncSend aSend= new AsyncSend(addressText.getText().toString(),Integer.parseInt(portText.getText().toString()), messageText.getText().toString());
                    aSend.execute();
                }
            });
            return rootView;
        }

        public class AsyncSend extends AsyncTask<Void, Void, Void> {
            String address;
            int port;
            String message;
            String response;
            AsyncSend(String addr, int p, String mes) {
                address = addr;
                port = p;
                message = mes;
            }

            @Override
            protected Void doInBackground(Void... params) {
                android.os.Debug.waitForDebugger();
                Socket socket = null;
                try {
                    System.out.println("Test");
                    socket = new Socket(address, port);
                    System.out.println("Test");
                    DataOutputStream writeOut = new DataOutputStream(socket.getOutputStream());
                    writeOut.writeUTF(message);
                    writeOut.flush();


                    ByteArrayOutputStream writeBuffer = new ByteArrayOutputStream(1024);
                    byte[] buffer = new byte[1024];

                    int bytesRead;
                    InputStream writeIn = socket.getInputStream();

                    while((bytesRead = writeIn.read(buffer)) != -1) {
                        writeBuffer.write(buffer,0,bytesRead);
                        response += writeBuffer.toString("UTF-8");
                    }
                } catch (UnknownHostException e){
                    e.printStackTrace();
                    response = "Unknown HostException: " + e.toString();
                    System.out.println(response);
                } catch (IOException e) {
                    response = "IOException: " + e.toString();
                    System.out.println(response);
                } finally {
                    if (socket != null) {
                        recieve.setText(response);
                        try {
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                recieve.setText(response);
                super.onPostExecute(result);
            }
        }
    }

服务器代码:

import http.server
import socket
import threading
import socketserver

import pymongo

import smtplib

class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        #Connect to database
        try:
            from pymongo import MongoClient
            dbclient = MongoClient()
            db = dbclient.WDI_database
            print("Database Connected")
        except pymongo.errors.ConnectionFailure as e:
            print("Database Failed: {}".format(e))

        col = db.users

        data2 = str(self.request.recv(1024), 'ascii')
        print("Server: {}".format(data2));
        data = data2.split("||")
        username, password, camunits, homunits = data[0], data[1], data[2], data[3]
        post = {"user": username,
                "pass": password,
                "cam": camunits,
                "disp": homunits}
        col.insert(post)
        print(col.count())

        cur_thread = threading.current_thread()
        response = bytes("{} Received data for: {}".format(cur_thread, username), 'ascii')
        self.request.sendall(response)

class ThreadedUDPRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request[0].strip()
        socket = self.request[1]
        print("Recieved: " + data.decode("utf-8"))
        socket.sendto(data.upper(), self.client_address)

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

if __name__ == "__main__":
    # Port 0 means to select an arbitrary unused port
    HOST, PORT = "", 5000

    tcpserver = ThreadedTCPServer((HOST, PORT-1), ThreadedTCPRequestHandler)
    server_thread = threading.Thread(target=tcpserver.serve_forever)
    server_thread.daemon = True
    server_thread.start()
    print("TCP serving at port", PORT-1)

    while True:
        pass
    tcpserver.shutdown()

【问题讨论】:

    标签: android python sockets


    【解决方案1】:

    使用Socket 类对于您的目的来说太低级并且充满了潜在的陷阱。我建议改用org.apache.http.client.HttpClient

    【讨论】:

    • 我可以保持服务器不变,还是我也必须重新编码服务器?
    • 不,不需要在服务器上进行任何更改。只要您使用的是 HTTP 协议,HttpClient 就适合您!
    • 感谢您的建议,我会记住这一点。这个项目的另一部分我没有提到:这个客户端/服务器动态也必须被镜像,但服务器是一个定制的硬件,可能无法处理 HTTP 连接,所以我想使连接尽可能低或简单。
    【解决方案2】:

    这可能是因为我没有转发端口,所以我的连接被我的路由器阻止了。我在路由器和 Windows 上都打开了端口。

    【讨论】: