基于本教程和另一个不幸的是我现在无法掌握的教程,我创建了我的客户端-服务器应用程序,但客户端没有发送字符串消息,而是从以下位置请求数据(使用对象输入/输出流)服务器使用自定义类“消息”。
首先,我创建了它的基本概念,使用简单的 Java 并在我的计算机上测试了服务器和客户端,并在控制台输出中显示了我的客户端接收到的数据。一切都很好,所以我开始过渡到 Android(对于客户端)。尝试使用 AsycTask,如链接教程中所示,到目前为止,我已经设法在客户端和服务器之间建立连接。但是我在让我的服务器读取我的“消息”对象时遇到了问题。
服务器:
import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class T_Server extends Thread {
private static int port = 4444;
private ServerSocket srvSock = null;
private Socket clntSock = null;
private boolean running = false;
private ObjectInputStream in;
private ObjectOutputStream out;
private OnMessageReceived msgListener;
private Message msgIn;
private Object objSend;
public static void main(String[] args) {
OnMessageReceived _msgListener=new OnMessageReceived();
T_Server server=new T_Server(_msgListener);
server.start();
}
public T_Server(OnMessageReceived _msgListener) {
this.msgListener = _msgListener;
}
public void send(Object _msg) {
if (out != null) {
try {
out.writeObject(_msg);
out.flush();
} catch (IOException ex) {
Logger.getLogger(T_Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
public void run() {
running = true;
try {
srvSock = new ServerSocket(port);
System.out.println("Server startet. IP : " + InetAddress.getLocalHost() + ", Port : " + srvSock.getLocalPort());
System.out.println("\nWaiting for a client ...");
clntSock = srvSock.accept();
System.out.println("\nClient accepted: " + clntSock);
try {
out = new ObjectOutputStream(clntSock.getOutputStream());
in = new ObjectInputStream(clntSock.getInputStream());
while (running) {
msgIn = (Message) in.readObject();
System.out.println(msgIn.toString());
objSend = msgListener.messageReceived(msgIn);
send(objSend);
}
} catch (Exception e) {
System.out.println("S: Error");
e.printStackTrace();
} finally {
clntSock.close();
}
} catch (Exception e) {
System.out.println("S: Error");
e.printStackTrace();
}
}
}
我在服务器和客户端消息类上都使用相同的 消息类:
import java.io.Serializable;
public class Message implements Serializable{
private static final long serialVersionUID = 1L;
public String sender, content, type;
public Message(String sender, String type, String content){
this.sender = sender; this.type=type; this.content = content;
}
@Override
public String toString(){
return "{type='"+type+"', sender='"+sender+"', content='"+content+"'}";
}
}
我还在服务器端创建了一个类来处理消息,称为 OnMessageReceived。
PS 在这个类中,有一些字段和一些选项与我的后端数据库有关。
OnMessage 接收:
import java.sql.SQLException;
import java.util.regex.Pattern;
public class OnMessageReceived {
public Object messageReceived(Message message) throws SQLException {
Message _msg = message;
Database db = new Database();
Object objReturn;
String strResult;
boolean addResult;
final Pattern pattern = Pattern.compile("\\[.*?&");
final String[] result;
if (_msg.type.equals("getUsers")) {
objReturn = db.getUsers();
return objReturn;
} else if (_msg.type.equals("getFriends")) {
objReturn = db.getFriends(_msg.sender);
return objReturn;
} else if (_msg.type.equals("addFriend")) {
String _UserName, _UserNameFriend;
_UserName = _msg.sender;
_UserNameFriend = _msg.content;
addResult = db.addFriend(_UserName, _UserNameFriend);
if (addResult) {
strResult = "Add was successfull";
return strResult;
} else if (!addResult) {
strResult = "Add failed";
return strResult;
}
System.out.println(addResult);
} else if (_msg.type.equals("addUser")) {
String _UserName, _Password, _Phone;
result = pattern.split(_msg.content);
_UserName = _msg.sender;
_Password = result[0];
_Phone = result[1];
addResult = db.addUser(_UserName, _Password, _Phone);
if (addResult) {
strResult = "Add was successfull";
return strResult;
} else if (!addResult) {
strResult = "Add failed";
return strResult;
}
System.out.println(addResult);
} else if (_msg.type.equals("Login")) {
boolean isUser;
String _UserName;
_UserName = _msg.sender;
isUser = db.isUser(_UserName);
if (isUser) {
strResult = "Login Successfull";
return strResult;
} else if (!isUser) {
strResult = "Login failed";
return strResult;
}
}
return null;
}
}
对于客户端(在 Android 上),它与链接教程中的非常相似。不同之处在于我只有 2 个按钮,一个用于连接服务器,一个用于发送我的消息,这是我的 Message 类的一个实例。
客户:
import java.io.*;
import java.net.*;
import android.util.Log;
public class T_Client {
private static final String TAG = "MyActivity";
private static String serverIP = "192.168.1.11";
private static int port = 4444;
private InetAddress serverAddr = null;
private Socket sock = null;
private boolean running = false;
private ObjectInputStream in;
private ObjectOutputStream out;
private OnMessageReceived msgListener;
Object objIn, objReceived;
public T_Client(OnMessageReceived _msgListener){
this.msgListener=_msgListener;
}
public void send(Message _msg) {
if (out != null) {
try {
out.writeObject(_msg);
out.flush();
Log.i(TAG,"Outgoing : " + _msg.toString());
} catch (IOException ex) {
Log.e(TAG,ex.toString());
}
}
}
public void stopClient(){
running = false;
}
public void run(){
running = true;
try {
//here you must put your computer's IP address.
serverAddr = InetAddress.getByName(serverIP);
Log.i("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
sock = new Socket(serverAddr, port);
try {
//send the message to the server
out =new ObjectOutputStream(sock.getOutputStream());
//receive the message which the server sends back
in =new ObjectInputStream(sock.getInputStream());
Log.i("TCP Client", "C: Connected.");
//in this while the client listens for the messages sent by the server
while (running) {
objIn = in.readObject();
if (objIn != null && msgListener != null) {
//call the method messageReceived from MyActivity class
msgListener.messageReceived(objIn);
}
objIn = null;
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + objIn + "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
sock.close();
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
public interface OnMessageReceived {
public void messageReceived(Object objReceived);
}
}
主要活动:
import java.io.IOException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private static final String TAG = "MyActivity";
private T_Client client;
private Message msgSend;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void connect(View v) throws IOException {
new connectTask().execute("");
}
public void btnSend(View v) throws IOException {
msgSend=new Message("Setlios", "getUsers", "");
if(client!=null){
client.send(msgSend);
}
}
public class connectTask extends AsyncTask<Object,Object,T_Client> {
@Override
protected T_Client doInBackground(Object... objIn) {
//we create a TCPClient object and
client = new T_Client(new T_Client.OnMessageReceived() {
@Override
//here the messageReceived method is implemented
public void messageReceived(Object objIn) {
//this method calls the onProgressUpdate
publishProgress(objIn);
}
});
client.run();
return null;
}
@Override
protected void onProgressUpdate(Object... values) {
super.onProgressUpdate(values);
Log.i(TAG,values.getClass().getName().toString());
}
}
}
当我点击“发送”按钮时,我在服务器控制台上收到此错误,它指向我读取从 ObjectInputStream 读取的对象并将其传递给 Message 类的实例但我不明白问题出在哪里. 我还注意到它显示了这个“in.neverhide.connect”,这是我的 android 客户端项目的包名称
java.lang.ClassNotFoundException: in.neverhide.connect.Message
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:622)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1593)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at Objects_WORKING.T_Server.run(T_Server.java:61)