server.accept做“app停止工作”

时间:2014-09-07 11:21:56

标签: android eclipse sockets

我正在尝试做客户端/服务器 但是服务器中存在问题 代码停在" server.accept()"并停止工作 这是服务器代码:

package com.example.do2do2messanger;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class Codes extends Activity {

private ServerSocket server;
private Socket connection;
private ObjectInputStream input;
private ObjectOutputStream output;
EditText sended;
TextView mirrored,chatwindow;
Button copied;

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

    // text view of the messages
    mirrored = (TextView) findViewById(R.id.mirror_id);
    sended = (EditText) findViewById(R.id.send_id);
    copied = (Button) findViewById(R.id.copy_id);
    chatwindow = (TextView) findViewById(R.id.chat_id);


    try
    {
        server = new ServerSocket(4444);
        mirrored.setText("c1");
        waitforconnection();


    }
    catch(IOException e)
    {
        mirrored.setText("c2");
        e.printStackTrace();
    }

}

private void waitforconnection() throws IOException
{
    showmessage("waiting for someone to connect ... \n");
    connection = server.accept(); // acts as infinte loop for listening
    //showmessage("Now connected to " + connection.getInetAddress().getHostName());

}

输出: 如果我评论server.accept() 它将给c1然后等待某人正常连接 但如果我离开它,它将停止应用程序并给出消息: "不幸的是,app停止了工作"

logcat的: 你的意思是:

09-07 06:48:44.430: E/AndroidRuntime(4777): FATAL EXCEPTION: main
09-07 06:48:44.430: E/AndroidRuntime(4777): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.do2do2messanger/com.example.do2do2messanger.Codes}: java.lang.NullPointerException
09-07 06:48:44.430: E/AndroidRuntime(4777):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at android.app.ActivityThread.access$600(ActivityThread.java:130)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at android.os.Handler.dispatchMessage(Handler.java:99)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at android.os.Looper.loop(Looper.java:137)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at android.app.ActivityThread.main(ActivityThread.java:4745)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at java.lang.reflect.Method.invokeNative(Native Method)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at java.lang.reflect.Method.invoke(Method.java:511)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at dalvik.system.NativeStart.main(Native Method)
09-07 06:48:44.430: E/AndroidRuntime(4777): Caused by: java.lang.NullPointerException
09-07 06:48:44.430: E/AndroidRuntime(4777):     at com.example.do2do2messanger.Codes.waitforconnection(Codes.java:67)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at com.example.do2do2messanger.Codes.onCreate(Codes.java:52)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at android.app.Activity.performCreate(Activity.java:5008)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
09-07 06:48:44.430: E/AndroidRuntime(4777):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)

1 个答案:

答案 0 :(得分:0)

您似乎发布了错误的logcat,因为它没有描述您遇到的问题。但我知道你的问题是什么。针对Android 3.0或更高版本的应用不允许在主线程上进行网络连接。

参见 NetworkOnMainThread | Android Developers

  

应用程序尝试执行时抛出的异常   在其主线程上进行网络操作。

     

这仅适用于针对Honeycomb SDK或。的应用程序   更高。允许使用早期SDK版本的应用程序   他们的主要事件循环线程上的网络,但它很重要   泄气。请参阅文档设计响应性。

解决方案

我建议您使用Service进行各种网络操作。我根据你自己的代码为你创建了这个例子:

<强> Codes.java

package com.example.do2do2messanger;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.nillerr.stackoverflow.R;

public class Codes extends Activity {

    /**
     * Service sends broadcasts, which are received by this BroadcastReceiver
     */
    private final BroadcastReceiver mSocketServerReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Bundle extras = intent.getExtras();

            String action = intent.getAction();
            if (action.equals(SocketServerService.ACTION_STATUS_CHANGED)) {
                onStatusChanged(extras.getString("message"));
            }
        }
    };

    EditText sended;
    TextView mirrored, chatwindow;
    Button copied;

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

        // text view of the messages
        mirrored = (TextView) findViewById(R.id.btn_start_service);
        sended = (EditText) findViewById(R.id.send_id);
        copied = (Button) findViewById(R.id.copy_id);
        chatwindow = (TextView) findViewById(R.id.chat_id);

        // Start the ServerSocket
        startService(new Intent(this, SocketServerService.class));
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Register our broadcast receiver to listen for ACTION_STATUS_CHANGED broadcasts
        LocalBroadcastManager.getInstance(this).registerReceiver(mSocketServerReceiver, new IntentFilter(SocketServerService.ACTION_STATUS_CHANGED));
    }

    @Override
    protected void onPause() {
        super.onPause();

        // I consider unregistering the receiver, when the activity is not visible, as good practice.
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mSocketServerReceiver);

        if (isFinishing()) {
            stopService(new Intent(this, SocketServerService.class));
        }
    }

    protected void onStatusChanged(String message) {
        // Update your message here
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    }
}

<强> SocketServerService.java

package com.example.do2do2messanger;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketServerService extends Service implements Runnable {

    public static final String ACTION_STATUS_CHANGED = "com.example.do2do2messanger.SocketServerService.STATUS_CHANGED";

    private Thread mThread;
    private boolean mRunning;

    private ServerSocket mServerSocket;

    private Socket mClientSocket;
    private InputStream mInputStream;
    private OutputStream mOutputStream;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        if (mThread != null) {
            return;
        }

        log("Starting thread");

        // Start a background thread for networking
        mRunning = true;
        mThread = new Thread(this);
        mThread.start();
    }

    @Override
    public void run() {
        try {
            sendStatusChanged("Starting server...");

            mServerSocket = new ServerSocket();
            mServerSocket.bind(new InetSocketAddress(4444));

            while (mRunning) {
                try {
                    sendStatusChanged("Waiting for someone to connect...");

                    // Wait for connection
                    mClientSocket = mServerSocket.accept();

                    mInputStream = mClientSocket.getInputStream();
                    mOutputStream = mClientSocket.getOutputStream();

                    // Start echoing
                    sendStatusChanged("Client connected");
                    for (int c = mInputStream.read(); c > -1; c = mInputStream.read()) {
                        mOutputStream.write(c);
                        mOutputStream.flush();
                    }
                } catch (IOException ignored) {
                } finally {
                    closeClient();
                }
            }
        } catch (IOException ignored) {
        } finally {
            // Will eventually call onDestroy()
            stopSelf();
        }
    }

    private void sendStatusChanged(String message) {
        Intent intent = new Intent(ACTION_STATUS_CHANGED);
        intent.putExtra("message", message);

        // Send a local broadcast, which can be received by a registered BroadcastReceiver
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    private void closeClient() {
        try {
            if (mInputStream != null) {
                mOutputStream.close();
            }

            if (mOutputStream != null) {
                mOutputStream.close();
            }

            if (mClientSocket != null) {
                mClientSocket.close();
            }
        } catch (IOException ignored) {
        } finally {
            sendStatusChanged("Client disconnected");
        }
    }

    private void closeServer() {
        try {
            if (mServerSocket != null) {
                mServerSocket.close();
            }
        } catch (IOException ignored) {
        } finally {
            sendStatusChanged("Server closed");
        }
    }

    private void log(String message) {
        Log.d(getClass().getSimpleName(), message);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        if (mThread == null) {
            return;
        }

        log("Stopping thread");

        mRunning = false;

        closeServer();

        try {
            mThread.join();
            mThread = null;
        } catch (InterruptedException ignored) {
        }

        log("Thread stopped");
    }
}

<强>的AndroidManifest.xml 您想在<application>标记中添加以下内容:

<service android:name="com.example.do2do2messanger.SocketServerService" />