我正在开发简单的Android到Java应用程序,我希望它们与类Message进行通信,如下所示:
public class Message implements Serializable {
/**
*
*/
private static final long serialVersionUID = 120L;
private MessageType type;
private Object content;
public Message(MessageType type, Object content) {
this.type = type;
this.content = content;
}
public String toString() {
StringBuilder string = new StringBuilder();
string.append(type).append(System.getProperty("line.separator"));
if (content != null) {
string.append(content.toString());
}
return string.toString();
}
//======== Getters and Setters ===========
...
}
对象内容始终是User,非常简单。
现在,Java服务器接收Android注册请求,并回答可用用户列表。 还有一些其他请求/响应通信,但它不是重点。
现在,有时我对Android客户端和Java服务器之间的通信没有任何问题,但有时会抛出classCastException(在Android和Java上)。
我在两侧都有两个线程,用于在同一个套接字上发送和接收消息。 我是否必须制作两个单独的插座用于发送和接收,我怀疑?
有没有人有这个想法或经验? 是否与多线程或互联网连接无关?
修改
在Message中对象content
字段的类型是灵活的(我需要它在这里传递一些其他类,但是现在,我总是发送用户类:
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 123L;
private String name;
private String IP;
private int tcpPort;
private int bufferSize;
public User(User user) {
this.name = new String(user.name);
this.IP = new String(user.IP);
this.tcpPort = user.tcpPort;
this.bufferSize = user.bufferSize;
}
public Integer getHashCode() {
return ((String) (IP + tcpPort)).hashCode();
}
public String toString() {
StringBuilder string = new StringBuilder();
string.append(name).append(System.getProperty("line.separator"));
string.append(IP).append(System.getProperty("line.separator"));
string.append(tcpPort).append(System.getProperty("line.separator"));
return string.toString();
}
这是简单的用户类。
这是我在服务器端做的事情:
- 服务器接收等待来自客户端的新请求并将其添加到新连接列表 - Waiter.pendingConnections
(if语句)。
- 如果没有新请求,则线程将从soTimeout周期开始接收来自现有连接的新消息。
注意:ClientTcpConnector
和ServerTcpConnector
是套接字,输入和输出流以及东西的包装器(由于复杂性,我现在不会发布这些类...)
public class DispatchingManager extends Thread {
private final static Logger Log = LogManager.getLogger(Connector.class.getName());
private static final int SERVER_WAITING_PORT = 50001;
public static final ServerTcpConnector syncConnector = new ServerTcpConnector(SERVER_WAITING_PORT);
private final int SOCKET_TIMEOUT_PERIOD = 300;
@Override public void run() {
/* InetAddress remoteIPaddress = syncConnector.waitConnection(); */
ClientTcpConnector awaitedConnector;
boolean isReceived = false;
while (!isInterrupted()) {
//wrapper for socket.accept() with soTimeout argument
awaitedConnector = syncConnector.waitRequest(SOCKET_TIMEOUT_PERIOD);
if (awaitedConnector != null) {
Log.debug("New connection - available");
awaitedConnector.connect();
awaitedConnector.receive();
Waiter.pendingConnections.addFirst(new CompleteUser(null, awaitedConnector));
} else {
for (CompleteUser user : Waiter.onlineConnections.values()) {
awaitedConnector = (ClientTcpConnector) user.getConnector();
isReceived = awaitedConnector.receive(SOCKET_TIMEOUT_PERIOD);
if (isReceived) {
Log.debug("Message received from: " + user.getNetworkUser().getName());
Waiter.pendingConnections.addFirst(user);
isReceived = false;
}
}
}
}
}
}
我的服务器设计为几乎没有线程接收来自Waiter.pendingConnections
的请求,并通过对客户端的响应来处理它们。现在我只有一个线程处理挂起的连接。
在客户端这是(非常相似): 这是WelcomeActivity之后的主要线程。
...
@Override
public void run() {
tcpConnector = new TcpConnector(remoteServerIP, remoteServerPort);
while (true) {
registerWithServer();
sendTCPThread = new Thread(new Runnable() {
@Override
public void run() {
sendDataToServer();
}
}, "sendTCPThread");
sendTCPThread.start();
waitNewServerMessages();
sendTCPThread.interrupt();
}
}
private void sendDataToServer() {
while (!Thread.interrupted()) {
try {
Message message = getSendingMessageQueue().takeFirst();
tcpConnector.send(message);
Log.d(TAG, "Sent message - " + message.toString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static boolean waitNewServerMessages() {
Message newMessage;
while (!syncManager.interrupted()) {
newMessage = (Message) tcpConnector.receiveObject();
if (newMessage != null) {
switch (newMessage.getType()) {
case NEW_USER:
onlineUsers.add((User) newMessage.getContent());
updateUIWith((User) newMessage.getContent(),
AppState.IDLE);
break;
case END_ADDING:
break;
case DISCONNECTED_USER:
updateUIWith((User) newMessage.getContent(),
AppState.DISCONNECTED_USER);
break;
case DISCONNECT:
syncManager.interrupt();
break;
default:
break;
}
Log.d(TAG, "Receive message - " + newMessage.toString());
}
}
return true;
}
基本上这是接收和发送消息的结构,代码太长而无法完全发布,但我可以做到......
最大的问题是我有时可以完成沟通,但有时我不能......我知道我发送接收代码是好的,因为有时一切都还可以。但另一方面我不知道如何调试它,因为它有时会抛出这个异常:
11:48:34.002 [Thread-1] DEBUG networkUtils.connectors.Connector - ClassCastException:
java.lang.ClassCastException: java.io.ObjectStreamClass cannot be cast to networkUtils.networkMessage.Message
at networkUtils.connectors.ClientTcpConnector.receive(ClientTcpConnector.java:42) [bin/:?]
at networkUtils.connectors.ClientTcpConnector.receive(ClientTcpConnector.java:75) [bin/:?]
at networkUtils.DispatchingManager.run(DispatchingManager.java:37) [bin/:?]
11:48:34.609 [Thread-1] DEBUG networkUtils.connectors.Connector - ClassCastException:
java.lang.ClassCastException: networkUtils.beans.User cannot be cast to networkUtils.networkMessage.Message
at networkUtils.connectors.ClientTcpConnector.receive(ClientTcpConnector.java:42) [bin/:?]
at networkUtils.connectors.ClientTcpConnector.receive(ClientTcpConnector.java:75) [bin/:?]
at networkUtils.DispatchingManager.run(DispatchingManager.java:37) [bin/:?]
11:48:35.219 [Thread-1] DEBUG networkUtils.connectors.Connector - ClassCastException:
java.lang.ClassCastException: networkUtils.networkMessage.MessageType cannot be cast to networkUtils.networkMessage.Message
at networkUtils.connectors.ClientTcpConnector.receive(ClientTcpConnector.java:42) [bin/:?]
at networkUtils.connectors.ClientTcpConnector.receive(ClientTcpConnector.java:75) [bin/:?]
at networkUtils.DispatchingManager.run(DispatchingManager.java:37) [bin/:?]
我知道问题出在哪里,但我不知道为什么会这样。 :(
谢谢, 此致