-1

我正在处理一次需要两个或多个套接字连接的项目。我注意到,在 android 4.x 之前,我的应用程序正常工作,而在 android 4.0.4 上,它在第二次连接时什么也不做。我做了一个简单的项目来确保它是这样的,在早期版本中,两个连接是好的,在 4.0.4 它什么都不做,没有错误,没有异常,没有日志消息....

如何在 android 4.0.4 中一次连接两个套接字

我的测试服务器

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;


public class Main {

public static void main(String[] args) throws IOException {
    ServerSocket socket1 = new ServerSocket(9045);
    ServerSocket socket2 = new ServerSocket(9046);

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    Listener th1 = new Listener(socket1, "||");
    Listener th2 = new Listener(socket2, "==");

    System.out.println("Starting....");

    new Thread(th1).start();
    new Thread(th2).start();
    while (true){
        if (br.readLine().endsWith("exit"))
            break;
    }
    th1.stop();
    th2.stop();

    socket1.close();
    socket2.close();
}

}

class Listener implements Runnable{

int i = 1;
boolean isRunning = true;
ServerSocket socket;
String tag;

public Listener(ServerSocket socket1, String tag) {
    socket = socket1;
    this.tag = tag;
}

@Override
public void run() {
    System.out.println(tag + " started");
    while (isRunning){
        try {
            socket.accept();
            System.out.println(tag + " accepted " + i++);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public void stop() {
    isRunning = false;
}

}

安卓项目

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hello_world" />

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_below="@+id/textView1"
            android:text="Start 1"
            android:onClick="clickStart1" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignRight="@+id/button1"
            android:layout_below="@+id/button1"
            android:text="Start 2"
            android:onClick="clickStart2" />

    </RelativeLayout>

MainActivity.java

package com.example.twosocketsapk;

    import com.example.twosocketsapk.SocketClientTask.SocketListener;

    import android.app.Activity;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.view.View;

    public class MainActivity extends Activity implements SocketListener{

        SocketClientTask task1;
        SocketClientTask task2;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            task1 = new SocketClientTask(this, "192.168.0.21", 9045);
            task2 = new SocketClientTask(this, "192.168.0.21", 9046);

        }

        public void clickStart1(View v) {
            if (task1.getStatus() != AsyncTask.Status.RUNNING)
                task1.execute();
        }

        public void clickStart2(View v) {
            if (task2.getStatus() != AsyncTask.Status.RUNNING)
                task2.execute();
        }

        @Override
        public void onConnect(String message) {

        }

        @Override
        public void onGetMessage(String message) {

        }

    }

SocketClientTask.java

package com.example.twosocketsapk;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;

    import android.os.AsyncTask;
    import android.util.Log;

    public class SocketClientTask extends AsyncTask<String, String, String> {
        private static final String TAG = SocketClientTask.class.getSimpleName();
        private SocketListener messageHandler;

        private Socket socket = null;
        private PrintWriter socketOut = null;
        private BufferedReader socketIn = null;

        private Boolean isConnected = false;

        String  ip;
        int     port;

        private boolean isRunning = true;

        public SocketClientTask(SocketListener messageHandler, String ip, int port) {
            this.messageHandler = messageHandler;
            this.ip = ip;
            this.port = port;
        }

        public Boolean isConnected() {
            return isConnected;
        }

        public void runReading() throws UnknownHostException, IOException{
            socket = new Socket(ip, port);
            socketOut = new PrintWriter(socket.getOutputStream(), true);
            socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            isConnected = true;
            while (isRunning) {
                publishProgress(socketIn.readLine());
            }
            socketOut.close();
            socketIn.close();
            socket.close();
        }

        public boolean sendMessage(String line) {
            if (socketOut != null && !socketOut.checkError()) {
                socketOut.println(line);
                socketOut.flush();
                return true;
            } else {
                Log.w(TAG, "message: " + line + "; wasn't sent");
                return false;
            }
        }

        @Override
        protected String doInBackground(String... params) {
            try {
                runReading();
            } catch (UnknownHostException e) {
                isConnected = false;
                Log.e(TAG, "Socket Client ERROR", e);
            } catch (IOException e) {
                isConnected = false;
                Log.e(TAG, "Socket Client ERROR", e);
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            messageHandler.onGetMessage(values[0]);
        }

        public void stop() {
            isRunning = false;
        }

        // --

        public interface SocketListener {
            void onConnect(String message);
            void onGetMessage(String message);
        }

    }

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.twosocketsapk"
        android:versionCode="1"
        android:versionName="1.0" >

        <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="17" />
        <uses-permission android:name="android.permission.INTERNET"/>

        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="com.example.twosocketsapk.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>

    </manifest>

PS对不起我的英语,这不是我的母语

4

1 回答 1

0

如果确实没有例外,您正在阅读线路,但您没有发送线路。

readLine() 可以返回 null,您不检查它。

于 2013-04-26T10:02:02.020 回答