1

编辑:虽然标记为重复,但我的情况与其他情况不同。我发现序列化对象在输入和输出流上都需要相同的包名称。不匹配的包名称是我的问题。

我有一个 Java 服务器和客户端。它们能够通过套接字连接并使用 ObjectInputStream 和 ObjectOutputStream 来回发送对象数据包。我试图在 Android 中实现客户端。Android 客户端连接但我无法使用流。

在我当前的实现中,我的 Android 客户端必须与我的 PC 位于同一网络上,并且服务器正在运行。我的电脑也有一个静态 IP 192.168.1.3。我得到的错误是

java.io.StreamCorruptedException:无效类型代码:AC。

我会发布我的桌面服务器和客户端的代码,但我的字符用完了。我从这里得到了代码。我已经修改了该代码,因此当客户端连接时不需要字符串。用户发送一个 ChatMessage(或我重命名的 Packet),消息内容与 ClientThread 一起存储。客户端能够请求他们发送的最后一条消息,服务器将其返回。

如何在 Android 客户端中正确使用对象流?

主要活动:

package com.example.androidclient;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {
  Button btnGetLastMessage, btnSend, btnLogout;
  TextView textStatus;
  EditText textMessage;
  NetworkTask networktask;
  private Socket nsocket; // Network Socket
  private ObjectInputStream nis; // Network Input Stream
  private ObjectOutputStream nos; // Network Output Stream

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

    btnGetLastMessage = (Button) findViewById(R.id.btnGetLastMessage);
    btnSend = (Button) findViewById(R.id.btnSend);
    btnLogout = (Button) findViewById(R.id.btnLogout);
    textStatus = (TextView) findViewById(R.id.textStatus);
    textMessage = (EditText) findViewById(R.id.textMessage);

    btnGetLastMessage.setOnClickListener(btnGetLastMessageListener);
    btnSend.setOnClickListener(btnSendListener);
    btnLogout.setOnClickListener(btnLogoutListener);

    networktask = new NetworkTask();
    networktask.execute();
  }

  private OnClickListener btnLogoutListener = new OnClickListener() {
    public void onClick(View v) {
      networktask.SendDataToNetwork(new Packet(
          Packet.GET_LAST_MESSAGE));
    }
  };
  private OnClickListener btnGetLastMessageListener = new OnClickListener() {
    public void onClick(View v) {
      Packet msg = new Packet(Packet.GET_LAST_MESSAGE);
      networktask.SendDataToNetwork(msg);
    }
  };
  private OnClickListener btnSendListener = new OnClickListener() {
    public void onClick(View v) {
      textStatus.setText("Sending Message to AsyncTask.");
      Packet msg = new Packet(Packet.SEND_MESSAGE,
          textMessage.getText().toString());
      networktask.SendDataToNetwork(msg);
    }
  };

  public class NetworkTask extends AsyncTask<Void, byte[], Boolean> {

    @Override
    protected void onPreExecute() {
      Log.i("AsyncTask", "onPreExecute");
    }

    @Override
    protected Boolean doInBackground(Void... params) { // This runs on a
                              // different thread
      boolean result = false;
      try {
        Log.i("AsyncTask", "doInBackground: Creating socket");
        SocketAddress sockaddr = new InetSocketAddress("192.168.1.3",
            15000);
        nsocket = new Socket();
        nsocket.connect(sockaddr); // 10 second connection timeout

        if (nsocket.isConnected()) {
          // Creating both Data Stream
          try {
            nis = new ObjectInputStream(nsocket.getInputStream());
            nos = new ObjectOutputStream(nsocket.getOutputStream());
          } catch (IOException eIO) {
            Log.i("AsyncTask",
                "doInBackground: Exception creating new Input/output Streams: "
                    + eIO);
            eIO.printStackTrace();
            return false;
          }
          // creates the Thread to listen from the server

          Log.i("AsyncTask",
              "doInBackground: Socket created, streams assigned, listening from server");

          while (true) {
            Log.i("AsyncTask",
                "doInBackground: Waiting for data from the server...");
            try {
              Packet messageFromServer = (Packet) nis
                  .readObject();
              Log.i("ListenFromServer", "messageFromServer: "
                  + messageFromServer.getMessage());
              textStatus.setText("Last message: "
                  + messageFromServer.getMessage());
            } catch (IOException e) {
              Log.i("ListenFromServer",
                  "Server has close the connection: " + e);
              e.printStackTrace();
              break;
            } catch (ClassNotFoundException e2) {
              // Do nothing
            } catch (Exception e) {
              Log.i("ListenFromServer", "Generic exception: " + e);
              e.printStackTrace();
              break;
            }

          }
        }

      } catch (IOException e) {
        Log.i("AsyncTask", "doInBackground: IOException");
        e.printStackTrace();
        result = true;
      } catch (Exception e) {
        Log.i("AsyncTask", "doInBackground: Exception");
        e.printStackTrace();
        result = true;
      } finally {
        try {
          nis.close();
          nos.close();
          nsocket.close();
        } catch (IOException e) {
          e.printStackTrace();
        } catch (Exception e) {
          e.printStackTrace();
        }
        Log.i("AsyncTask", "doInBackground: Finished");
      }
      return result;
    }

    public void disconnect() {
      try {
        nis.close();
        nos.close();
        nsocket.close();
      } catch (Exception e) {
        Log.i("AsyncTask", "disconnect: Exception: " + e);
        e.printStackTrace();
      }
    }

    public void SendDataToNetwork(Packet msg) { // You run this from
                              // the
      // main thread.

      try {
        if (nsocket.isConnected()) {
          Log.i("AsyncTask",
              "SendDataToNetwork: Writing received message to socket");
          try {
            nos.writeObject(msg);
            nos.flush();
          } catch (IOException eIO) {
            Log.i("AsyncTask",
                "doInBackground:  Exception during login: "
                    + eIO);
            eIO.printStackTrace();
            nis.close();
            nos.close();
            nsocket.close();
          }
        } else {
          Log.i("AsyncTask",
              "SendDataToNetwork: Cannot send message. Socket is closed");
        }
      } catch (Exception e) {
        Log.i("AsyncTask",
            "SendDataToNetwork: Message send failed. Caught an exception");
        e.printStackTrace();
      }
    }

    @Override
    protected void onProgressUpdate(byte[]... values) {
      if (values.length > 0) {
        Log.i("AsyncTask", "onProgressUpdate: " + values[0].length
            + " bytes received.");
        textStatus.setText(new String(values[0]));
      }
    }

    @Override
    protected void onCancelled() {
      Log.i("AsyncTask", "Cancelled.");
    }

    @Override
    protected void onPostExecute(Boolean result) {
      if (result) {
        Log.i("AsyncTask", "onPostExecute: Completed with an Error.");
        textStatus.setText("There was a connection error.");
      } else {
        Log.i("AsyncTask", "onPostExecute: Completed.");
      }
    }
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    networktask.cancel(true); // In case the task is currently running
  }
}

活动布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/textMessage"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="text"
        android:textSize="24sp" />

    <Button
        android:id="@+id/btnSend"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send Message" >
    </Button>

    <Button
        android:id="@+id/btnGetLastMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Get Last Message" >
    </Button>

    <Button
        android:id="@+id/btnLogout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Logout" >
    </Button>

    <TextView
        android:id="@+id/textStatus"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Status Goes Here"
        android:textSize="24sp" />

</LinearLayout>

安卓清单:

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <uses-permission android:name="android.permission.INTERNET" >
    </uses-permission>

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
    </uses-permission>

     <application
        android:allowBackup="true"
        android:debuggable="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.androidclient.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>
4

0 回答 0