我是 Java 中 TCP 协议的新手。我想做一个服务器-客户端聊天界面。我可以将消息从客户端发送到服务器,但是当我从服务器向客户端发送消息时,我的 android 应用程序突然崩溃。这是我的代码..Android客户端..
public class chatWithServer extends Fragment
{
private ListView mList;
private ArrayList<String> arrayList;
private MyCustomAdapter mAdapter;
Button send;
EditText editText;
String serverMessage;
PrintWriter out;
BufferedReader in;
private static final String HOST = "192.168.48.1";
private static final int PORT = 5000;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
//super.onCreate(savedInstanceState);
final View myFragmentView = inflater.inflate(
R.layout.activity_main, container, false);
arrayList = new ArrayList<String>();
editText = (EditText)myFragmentView. findViewById(R.id.editText);
send = (Button)myFragmentView.findViewById(R.id.send_button);
send.setOnClickListener(onClickSend(myFragmentView));
//relate the listView from java to the one created in xml
mList = (ListView)myFragmentView.findViewById(R.id.list);
mAdapter = new MyCustomAdapter(getActivity(), arrayList);
mList.setAdapter(mAdapter);
connectServerTask();
return myFragmentView;
}
//-------->By clicking Send Button<---------//////
private OnClickListener onClickSend(final View myFragmentView) {
return new OnClickListener() {
@Override
public void onClick(View v) {
String message = editText.getText().toString();
//add the text in the arrayList
arrayList.add("c: " + message);
//sends the message to the server
sendToServer(message);
//refresh the list
mAdapter.notifyDataSetChanged();
editText.setText("");
}
};
}
private void connectServerTask() {
Runnable runnable= new Runnable() {
@Override
public void run() {
setSocket();
}
private void setSocket() {
try {
// Create Socket instance
Socket socket = new Socket(HOST, PORT);
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
out.println("Connected to Client");
try{
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
serverMessage =in.readLine();
if(serverMessage!=null) {
//sends the message to the server
chatUp(serverMessage);
}
serverMessage=null;
} catch (UnknownHostException e) {
e.printStackTrace();
} finally{
socket.close();
}
}catch (IOException e) {
e.printStackTrace();
}
}
private void chatUp(String message) {
arrayList.add(message);
mAdapter.notifyDataSetChanged();
}
};
new Thread(runnable).start();
}
//method of sending message to server
public void sendToServer(String message){
if (out != null && !out.checkError())
{
out.println(message);
out.flush();
};
}
}
Here is the code for Java-Server
public class TCPServer extends Thread {
public static final int SERVERPORT = 5000;
private boolean running = false;
private PrintWriter mOut;
private OnMessageReceived messageListener;
public static void main(String[] args) {
//opens the window where the messages will be received and sent
ServerBoard frame = new ServerBoard();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
/**
* Constructor of the class
* @param messageListener listens for the messages
*/
public TCPServer(OnMessageReceived messageListener) {
this.messageListener = messageListener;
}
/**
* Method to send the messages from server to client
* @param message the message sent by the server
*/
public void sendMessage(String message){
if (mOut != null && !mOut.checkError()) {
mOut.println(message);
mOut.flush();
}
}
@SuppressWarnings("resource")
@Override
public void run() {
super.run();
running = true;
try {
System.out.println("S: Connecting...");
//create a server socket. A server socket waits for requests to come in over the network.
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
//create client socket... the method accept() listens for a connection to be made to this socket and accepts it.
Socket client = serverSocket.accept();
System.out.println("S: Receiving...");
try {
//sends the message to the client
mOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);
//read the message received from client
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
//in this while we wait to receive messages from client (it's an infinite loop)
//this while it's like a listener for messages
while (running) {
String message = in.readLine();
if (message != null && messageListener != null) {
//call the method messageReceived from ServerBoard class
messageListener.messageReceived(message);
}
}
} catch (Exception e) {
System.out.println("S: Error");
e.printStackTrace();
} finally {
client.close();
System.out.println("S: Done.");
}
} catch (Exception e) {
System.out.println("S: Error");
e.printStackTrace();
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the ServerBoard
//class at on startServer button click
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
ServerBoard.java(用于服务器)
public class ServerBoard extends JFrame {//jFrame is for the desplaying the window and for nice GUI
private JTextArea messagesArea;//A JTextArea is a multi-line area that displays plain text.
private JButton sendButton;
private JTextField message;//JTextField is a lightweight component that allows the editing of a single line of text.
private JButton startServer;
private TCPServer mServer;
public ServerBoard() {
super("ServerBoard");
JPanel panelFields = new JPanel();
panelFields.setLayout(new BoxLayout(panelFields,BoxLayout.X_AXIS));
JPanel panelFields2 = new JPanel();
panelFields2.setLayout(new BoxLayout(panelFields2,BoxLayout.X_AXIS));
//here we will have the text messages screen
messagesArea = new JTextArea();
messagesArea.setColumns(30);
messagesArea.setRows(10);
messagesArea.setEditable(false);
sendButton = new JButton("Send");
sendButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// get the message from the text view
String messageText = message.getText();
// add message to the message area
messagesArea.append("\n" + messageText);
// send the message to the client
mServer.sendMessage(messageText);
// clear text
message.setText("");
}
});
startServer = new JButton("Start");
startServer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// disable the start button
startServer.setEnabled(false);
//creates the object OnMessageReceived asked by the TCPServer constructor
mServer = new TCPServer(new TCPServer.OnMessageReceived() {
@Override
//this method declared in the interface from TCPServer class is implemented here
//this method is actually a callback method, because it will run every time when it will be called from
//TCPServer class (at while)
public void messageReceived(String message) {
messagesArea.append("\n "+message);
}
});
mServer.start();
}
});
//the box where the user enters the text (EditText is called in Android)
message = new JTextField();
message.setSize(200, 20);
//add the buttons and the text fields to the panel
panelFields.add(messagesArea);
panelFields.add(startServer);
panelFields2.add(message);
panelFields2.add(sendButton);
getContentPane().add(panelFields);
getContentPane().add(panelFields2);
getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.Y_AXIS));
setSize(300, 170);
setVisible(true);
}
}
--已编辑--
10-24 17:04:07.039: E/AndroidRuntime(15911): FATAL EXCEPTION: Thread-1131
10-24 17:04:07.039: E/AndroidRuntime(15911): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5908)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:837)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.view.View.requestLayout(View.java:15792)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.view.View.requestLayout(View.java:15792)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.view.View.requestLayout(View.java:15792)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.view.View.requestLayout(View.java:15792)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.view.View.requestLayout(View.java:15792)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.view.View.requestLayout(View.java:15792)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.view.View.requestLayout(View.java:15792)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.widget.AbsListView.requestLayout(AbsListView.java:1837)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:813)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.widget.AbsListView$AdapterDataSetObserver.onChanged(AbsListView.java:5998)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
10-24 17:04:07.039: E/AndroidRuntime(15911): at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
10-24 17:04:07.039: E/AndroidRuntime(15911): at com.example.cardioapp.database.chatWithServer$2.display(chatWithServer.java:142)
10-24 17:04:07.039: E/AndroidRuntime(15911): at com.example.cardioapp.database.chatWithServer$2.setSocket(chatWithServer.java:123)
10-24 17:04:07.039: E/AndroidRuntime(15911): at com.example.cardioapp.database.chatWithServer$2.run(chatWithServer.java:94)
10-24 17:04:07.039: E/AndroidRuntime(15911): at java.lang.Thread.run(Thread.java:841)