我试图在 android 应用程序(作为服务器)和在 windows 上运行的基于 java 的客户端之间实现 tcp 套接字连接。(下面的简短版本,没有代码)
我使用一些传感器监听器来实现游戏运动(每个人都知道这种基于传感器的赛车游戏运动。
我已经为此目的实施了一项服务,该服务是从第一个活动开始的。该服务实现如下(我只是粘贴相关的代码片段,而不是整个类):
public class ServerService extends Service {
ConnectionHandler conHandler;
@Override
public void onCreate() {
startListener();
}
private void startListener() {
conHandler = new ConnectionHandler(this);
conHandler.execute();
}
private void sendMessage(String s)
{
conHandler.write(s);
}
public void messageNotify(String s) {
//Log.d("receivedMessage", s);
}
}
ConnectionHandler 类:
public class ConnectionHandler extends AsyncTask<Void, Void, Void>{
public static int serverport = 11111;
ServerSocket s;
Socket c;
ConnectionListening conListening;
ConnectionWriting conWriting;
DataOutputStream dos;
DataInputStream dis;
ServerService server;
public ConnectionHandler(ServerService server)
{
this.server = server;
}
@Override
protected Void doInBackground(Void... params) {
try {
Log.i("AsyncTank", "doInBackgoung: Creating Socket");
s = new ServerSocket(serverport);
} catch (Exception e) {
Log.i("AsyncTank", "doInBackgoung: Cannot create Socket");
}
try {
//this is blocking until client connects
c = s.accept();
Log.d("ConnectionHandler", "client connected");
dis = new DataInputStream(c.getInputStream());
dos = new DataOutputStream(c.getOutputStream());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
conWriting = new ConnectionWriting(this.c, this.dos);
conWriting.execute();
conListening = new ConnectionListening(this.c, this.dis, this.server);
if(this.c != null)
{
Timer timer = new Timer();
timer.schedule(conListening, 0, 10);
}
Log.i("AsyncTank", "doInBackgoung: Socket created, Streams assigned");
return null;
}
public void write(String s)
{
conWriting.writeToStream(s);
}
public void messageNotify(String s) {
// TODO method stub
}
}
ConnectionHandler 与 ConnectionWriting 类似地实现为 AsyncTask,因此 tcp 方法的阻塞不会影响整个通信。客户端能够向服务器发送消息。因为我不知道这条消息什么时候到达,所以我使用每 10 毫秒执行一次的 TimerTask 来检查是否有新消息。
ConnectionWriting 如下所示:
public class ConnectionWriting extends AsyncTask<Context, Void, Boolean>{
public DataOutputStream dos;
Socket c;
public ConnectionWriting(Socket c, DataOutputStream dos) {
this.dos = dos;
this.c = c;
}
@Override
protected Boolean doInBackground(Context... params) {
return true;
}
public void writeToStream(String s) {
try {
if (c != null){
//Log.i("AsynkTask", "writeToStream");
dos.writeBytes(s+"\n");
dos.flush();
Log.i("AsynkTask", "write: " +s);
} else {
Log.i("AsynkTask", "writeToStream : Cannot write to stream, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "writeToStream : Writing failed");
}
}
}
和 ConnectionListening 类: public class ConnectionListening extends TimerTask{
public DataInputStream dis;
Socket c;
ServerService server;
public ConnectionListening(Socket c, DataInputStream dis, ServerService server)
{
this.c = c;
this.dis = dis;
this.server = server;
}
@Override
public void run() {
String message = "";
try {
if (c != null) {
//Log.i("AsynkTask", "readFromStream : Reading message");
message = dis.readLine();
Log.i("AsynkTask", "read: " + message);
} else {
Log.i("AsynkTask", "readFromStream : Cannot Read, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "readFromStream : Writing failed");
}
if(message != null)
{
this.server.messageNotify(message);
}
}
}
我选择这种复杂的异步方式,因为服务器几乎是连续向客户端发送数据,并且存在客户端必须将数据发送回来的情况。使用 tcp 套接字的传统方式,不可能实现非阻塞通信,这意味着如果服务器正在发送(写入),读取功能阻塞,我永远不会收到客户端消息。
简而言之: 我测试了我的方法,但服务器总是先发送他的数据,然后再获取客户端消息。它不是异步的!?:-/
也许任何人都可以帮助我解决这个问题。或者有没有更简单的方法来实现这种方法?通信必须是异步的!并且必须自动完成读取(我试图用这种轮询方法来实现)。
我读过我可以使用一个线程进行读取,一个线程用于写入,但是我在使用写入功能(不知道如何在正在运行的线程中调用函数)和在我的活动中调用函数时遇到了问题。
我感谢每一个帮助!
问候