このチュートリアルと、残念ながら今は手に入らない別のチュートリアルに基づいて、クライアント サーバー アプリケーションを作成しましたが、文字列メッセージを送信する代わりに、クライアントは (オブジェクト入力/出力ストリームを使用して) データを要求し
ますカスタムクラス「メッセージ」を使用してサーバー。
最初に、単純な 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 このクラスには、バックエンド データベースに関係するフィールドといくつかのオプションがあります。
OnMessageReceived:
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) の場合、リンクされたチュートリアルのものと非常に似ています。違いは、サーバーに接続するためのボタンと、Message クラスのインスタンスであるメッセージを送信するためのボタンの 2 つしかないことです。
クライアント:
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 クラスのインスタンスを渡すポイントが示されますが、何が問題なのか理解できません。 . また、Androidクライアントのプロジェクトのパッケージ名であるこの「in.neverhide.connect」が表示されていることにも気付きました
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)