【发布时间】:2022-01-03 14:38:33
【问题描述】:
我正在构建一个多用户消息传递应用程序。我已经完成了服务器设置,但是我在用户(应用程序)部分遇到了问题。
client.java,创建异常的部分代码
public class Client {
public String photo;
public String clientPhoto;
public String clientId;
public PublicKey publicKey;
public PrivateKey privateKey;
public volatile Socket ClientSocket;
public InputStream in;
private ClientDatabase db;
private Encryption E;
private String ipv4 ;
private int port;
/**
* Consturactor need server ipv4 address and port to conndect it
*/
public Client(String ipv4,int port) throws IOException {
this.ipv4 = ipv4;
this.port = port;
}
/**
* Start recieving message form server
*
* */
public void startClient() {
try {
ClientSocket= new Socket(ipv4,5551);
ClientThread clientThread = new ClientThread(ClientSocket.getInputStream(),db,privateKey);
clientThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public ClientDatabase createDatabaseOnesTime(@Nullable Context context){
db = new ClientDatabase(context);
return db;
}
/**
* This function create key pair (public and private) every client needs to
* create their own key pair and they will store private key and publich publickey
*
* When I client want to send message to our client it should ecrypt message with our public key
* So ve can read data with our private key
*
* this funcion will start just ones time at installation of app
*
**/
@RequiresApi(api = Build.VERSION_CODES.O)
public void createPublicPrivateKey() throws NoSuchAlgorithmException, SQLException {
E = new Encryption();
E.generateKeyPair();
this.privateKey = E.getPrivate();
this.publicKey = E.getPublic();
this.db.addRootAuthTokens(this.E.encodeBase64FromPublicKey(publicKey),this.E.encodeBase64FromPrivateKey(privateKey));
}
还有 MainActivity.java
public class MainActivity extends AppCompatActivity {
private EditText edtPhoneNumber ;
private Button btnSignUp;
public static ClientDatabase database ;
public static Client client ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edtPhoneNumber = findViewById(R.id.edtPhoneNum);
btnSignUp = findViewById(R.id.btnSubmit);
client = null; // Client
try {
client = new Client("18.193.114.51", 5551);
} catch (IOException e) {
e.printStackTrace();
}
client.startClient();
database = client.createDatabaseOnesTime(MainActivity.this); // database
ClientThread 类
class ClientThread extends Thread{
private InputStream in;
private ClientDatabase db;
private Encryption E;
private PrivateKey privateKey;
byte[] data;
String message;
public ClientThread(InputStream in, ClientDatabase db,PrivateKey privateKey){
this.privateKey = privateKey;
this.db = db;
this.in = in;
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void run(){
/**
* Read everytime message and send message to message processor
*
*
**/
while (true){
try {
if (in.available()!= 0){
in.read(data);
message = new String(data);
messageProccessor(message);
}
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
}
我在 Client 类中使用 ClientThread 类接收所有传入消息并处理这些消息。通过使用客户端类中的一些函数,我使用了用户可能进行的活动。 问题是: 连接到 Socket 服务器时主要活动失败
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.ceng201_project, PID: 5412
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ceng201_project/com.example.ceng201_project.MainActivity}: android.os.NetworkOnMainThreadException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1448)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:355)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:356)
at java.net.Socket.connect(Socket.java:616)
at java.net.Socket.connect(Socket.java:565)
at java.net.Socket.<init>(Socket.java:445)
at java.net.Socket.<init>(Socket.java:217)
at com.example.ceng201_project.Client.startClient(Client.java:66)
at com.example.ceng201_project.MainActivity.onCreate(MainActivity.java:40)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
当我尝试在 ClientThread 类中建立 Socket 连接时,我无法从 Thread 类中获取连接的 Socket 对象,也无法运行其他应该工作的方法。例如,我无法向服务器发送消息。
我该如何解决这个问题? 提前致谢
【问题讨论】:
标签: java android multithreading sockets