我正在尝试读取非阻塞套接字,以避免在我的程序中遇到问题。有谁知道为什么当我尝试阅读总是返回零?这会是ByteBuffer的问题吗?在read方法中出现此问题,lenght始终为零。
package com.viewt.eyebird.communication;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.viewt.eyebird.PhoneInformation;
import com.viewt.eyebird.TrackingServiceData;
import com.viewt.eyebird.commands.*;
import android.os.Handler;
import android.util.Log;
final public class ServerCommunication {
protected final int socketTimeout;
protected final TrackingServiceData commandData;
protected final Handler handler;
protected final ServerCommunicationChecker clientChecker;
protected final LinkedList<Serialize> queue = new LinkedList<Serialize>();
protected final ByteBuffer socketBuffer = ByteBuffer.allocate(1024);
protected final StringBuilder readBuffer = new StringBuilder();
protected static final Pattern commandPattern = Pattern.compile(">[^<]+<");
protected static final ServerCommand availableCommands[] = { new Panic(),
new ChangeServer(), new GetServer(), new Restart(),
new PasswordCleanup() };
protected InetSocketAddress inetSocketAddress;
protected SocketChannel sChannel;
public ServerCommunication(Handler handler, String host, int port,
int timeAlive, int socketTimeout,
PhoneInformation phoneInformation, TrackingServiceData commandData) {
this.commandData = commandData;
this.handler = handler;
this.socketTimeout = socketTimeout;
try {
connect(host, port);
} catch (CommunicationException e) {
Log.getStackTraceString(e);
}
clientChecker = new ServerCommunicationChecker(handler, this,
timeAlive, new AliveResponse(phoneInformation));
handler.postDelayed(clientChecker, timeAlive);
}
public void connect() throws CommunicationException {
try {
sChannel = SocketChannel.open();
sChannel.configureBlocking(false);
sChannel.socket().setSoTimeout(socketTimeout);
sChannel.connect(inetSocketAddress);
} catch (IOException e) {
throw new CommunicationException(e);
}
}
public boolean isConnectionPending() {
return sChannel.isConnectionPending();
}
public boolean finishConnection() throws CommunicationException {
try {
return sChannel.finishConnect();
} catch (IOException e) {
throw new CommunicationException(e);
}
}
public void connect(String host, int port) throws CommunicationException {
inetSocketAddress = new InetSocketAddress(host, port);
connect();
}
public void send(Serialize serialize) throws CommunicationException {
try {
sChannel.write(ByteBuffer
.wrap(String.valueOf(serialize).getBytes()));
} catch (IOException e) {
throw new CommunicationException(e);
}
}
public void sendOrQueue(Serialize serialize) {
try {
send(serialize);
} catch (Exception e) {
queue(serialize);
}
}
public void queue(Serialize serialize) {
queue.add(serialize);
}
@Override
protected void finalize() throws Throwable {
handler.removeCallbacks(clientChecker);
super.finalize();
}
public void sync() throws CommunicationException {
int queueSize = queue.size();
for (int i = 0; i < queueSize; i++) {
send(queue.getFirst());
queue.removeFirst();
}
}
public void read() throws CommunicationException {
int length, readed = 0;
try {
while ((length = sChannel.read(socketBuffer)) > 0)
for (readed = 0; readed < length; readed++)
readBuffer.append(socketBuffer.get());
} catch (IOException e) {
throw new CommunicationException(e);
} finally {
socketBuffer.flip();
}
Matcher matcher = commandPattern.matcher(readBuffer);
int lastCommand;
if ((lastCommand = readBuffer.lastIndexOf("<")) != -1)
readBuffer.delete(0, lastCommand);
while (matcher.find()) {
for (ServerCommand command : availableCommands) {
try {
command.command(matcher.group(), commandData);
break;
} catch (CommandBadFormatException e) {
continue;
}
}
}
if (length == -1)
throw new CommunicationException("Server closed");
}
}
答案 0 :(得分:0)
您正在使用非阻塞通道,这意味着它将阻塞直到数据可用。如果没有数据可用,它会立即返回0而不会阻塞。
答案 1 :(得分:0)
应用程序始终从网络缓冲区读取。
您可能在发送一些数据后立即尝试读取,然后在获得0字节时停止读取。你甚至没有给网络任何时间来返回数据。
相反,你应该在一个循环中读取,如果没有数据,请使用Thread.sleep(time)
(使用大约100-300ms)稍微睡一觉,然后重试。
如果你已经等了太久,你应该停止循环:计算睡眠时间,当你得到一些数据时重置。或者在读取所有数据时停止。