fix(dev): fix bugs of json socket

This commit is contained in:
hyb1996
2018-09-11 16:06:18 +08:00
parent 8401ce40c6
commit 8c8d4bd89c
3 changed files with 46 additions and 25 deletions

View File

@@ -90,9 +90,17 @@ public class DevPluginService {
port = Integer.parseInt(host.substring(i + 1)); port = Integer.parseInt(host.substring(i + 1));
ip = host.substring(0, i); ip = host.substring(0, i);
} }
mConnectionState.onNext(new State(State.CONNECTING));
return createSocket(ip, port) return createSocket(ip, port)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.doOnNext(socket -> mSocket = socket); .doOnNext(socket -> {
mSocket = socket;
mConnectionState.onNext(new State(State.CONNECTED));
})
.doOnError(e -> {
mConnectionState.onNext(new State(State.DISCONNECTED));
e.printStackTrace();
});
} }
private Observable<JsonSocket> createSocket(String ip, int port) { private Observable<JsonSocket> createSocket(String ip, int port) {
@@ -131,10 +139,8 @@ public class DevPluginService {
public void log(String log) { public void log(String log) {
if (!isConnected()) if (!isConnected())
return; return;
JsonObject object = new JsonObject(); Observable.fromCallable(() ->
object.addProperty("type", "log"); writePair(mSocket, "log", new Pair<>("log", log)))
object.addProperty("log", log);
Observable.fromCallable(() -> mSocket.write(object))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace); .subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
} }

View File

@@ -13,12 +13,12 @@ import java.io.OutputStream;
import java.net.Socket; import java.net.Socket;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject; import io.reactivex.subjects.PublishSubject;
public class JsonSocket { public class JsonSocket {
private static final byte DELIMITER = '#'; private static final byte DELIMITER = '#';
private static final String DELIMITER_STRING = "#";
private static final String LOG_TAG = "JsonSocket"; private static final String LOG_TAG = "JsonSocket";
private final Socket mSocket; private final Socket mSocket;
@@ -39,7 +39,7 @@ public class JsonSocket {
public int write(JsonElement element) throws IOException { public int write(JsonElement element) throws IOException {
byte[] bytes = element.toString().getBytes(); byte[] bytes = element.toString().getBytes();
String length = String.valueOf(bytes.length) + DELIMITER; String length = bytes.length + DELIMITER_STRING;
mOutputStream.write(length.getBytes()); mOutputStream.write(length.getBytes());
mOutputStream.write(bytes); mOutputStream.write(bytes);
Log.d(LOG_TAG, "write: length = " + bytes.length + ", json = " + element); Log.d(LOG_TAG, "write: length = " + bytes.length + ", json = " + element);
@@ -85,41 +85,42 @@ public class JsonSocket {
private static class ByteQueue { private static class ByteQueue {
byte[] data; byte[] data;
int offset = 0; int offset = 0;
int length = 0; int size = 0;
public ByteQueue(int initialCapacity) { public ByteQueue(int initialCapacity) {
data = new byte[initialCapacity]; data = new byte[initialCapacity];
} }
int read(InputStream stream) throws IOException { int read(InputStream stream) throws IOException {
if (length >= data.length) { if (size >= data.length) {
resize(); resize();
} }
int end = offset + length; int end = offset + size;
int n; int n;
if (end >= data.length) { if (end >= data.length) {
n = stream.read(data, 0, offset); n = stream.read(data, 0, offset);
} else { } else {
n = stream.read(data, end, data.length - end); n = stream.read(data, end, data.length - end);
} }
length += n; size += n;
return n; return n;
} }
void pop(int len) { void pop(int len) {
if (len > length) { if (len > size) {
throw new IllegalArgumentException("pop " + len + " but current length is " + length); throw new IllegalArgumentException("pop " + len + " but current length is " + size);
} }
offset += len; offset += len;
if (offset >= data.length) { if (offset >= data.length) {
offset -= data.length; offset -= data.length;
} }
size -= len;
} }
String popAsString(int len) { String popAsString(int len) {
if (len > length) { if (len > size) {
throw new IllegalArgumentException("popAsString " + len + " but current length is " + length); throw new IllegalArgumentException("popAsString " + len + " but current length is " + size);
} }
int end = offset + len; int end = offset + len;
String str; String str;
@@ -127,8 +128,10 @@ public class JsonSocket {
str = new String(data, offset, len); str = new String(data, offset, len);
} else { } else {
byte[] bytes = new byte[len]; byte[] bytes = new byte[len];
System.arraycopy(data, offset, bytes, 0, data.length - offset); int firstPartLength = data.length - offset;
System.arraycopy(data, 0, bytes, data.length - offset, len - (data.length - offset)); int secondPartLength = len - firstPartLength;
System.arraycopy(data, offset, bytes, 0, firstPartLength);
System.arraycopy(data, 0, bytes, firstPartLength, secondPartLength);
str = new String(bytes); str = new String(bytes);
} }
pop(len); pop(len);
@@ -137,7 +140,16 @@ public class JsonSocket {
private void resize() { private void resize() {
byte[] newData = new byte[data.length * 2]; byte[] newData = new byte[data.length * 2];
System.arraycopy(data, 0, newData, 0, data.length); int end = offset + size;
if (end < data.length) {
System.arraycopy(data, offset, newData, 0, size);
} else {
int firstPartLength = data.length - offset;
int secondPartLength = offset + size - data.length;
System.arraycopy(data, offset, newData, 0, firstPartLength);
System.arraycopy(data, 0, newData, firstPartLength, secondPartLength);
}
offset = 0;
data = newData; data = newData;
} }
@@ -179,9 +191,11 @@ public class JsonSocket {
private void onChunk(ByteQueue byteQueue, int chunkSize) { private void onChunk(ByteQueue byteQueue, int chunkSize) {
if (mJsonDataLength <= 0) { if (mJsonDataLength <= 0) {
tryReadingJsonDataLength(byteQueue, chunkSize); tryReadingJsonDataLength(byteQueue, chunkSize);
}
if (mJsonDataLength <= 0) {
return; return;
} }
if (byteQueue.length < mJsonDataLength) { if (byteQueue.size < mJsonDataLength) {
return; return;
} }
String json = byteQueue.popAsString(mJsonDataLength); String json = byteQueue.popAsString(mJsonDataLength);
@@ -193,13 +207,15 @@ public class JsonSocket {
private void tryReadingJsonDataLength(ByteQueue byteQueue, int chunkSize) { private void tryReadingJsonDataLength(ByteQueue byteQueue, int chunkSize) {
int end = byteQueue.offset + byteQueue.length; int end = byteQueue.offset + byteQueue.size;
for (int i = 1; i <= chunkSize; i++) { int start = end - chunkSize;
if (byteQueue.data[end - i] == DELIMITER) { for (int i = start; i < end; i++) {
String jsonDataLength = new String(byteQueue.data, byteQueue.offset, end - i); if (byteQueue.data[i] == DELIMITER) {
String jsonDataLength = new String(byteQueue.data, byteQueue.offset, i - byteQueue.offset);
Log.d(LOG_TAG, "json data length = " + jsonDataLength); Log.d(LOG_TAG, "json data length = " + jsonDataLength);
byteQueue.pop(end - i + 1); byteQueue.pop(i - byteQueue.offset + 1);
receiveJsonDataLength(jsonDataLength); receiveJsonDataLength(jsonDataLength);
break;
} }
} }
} }

View File

@@ -270,7 +270,6 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
} }
private void onConnectException(Throwable e) { private void onConnectException(Throwable e) {
e.printStackTrace();
setChecked(mConnectionItem, false); setChecked(mConnectionItem, false);
Toast.makeText(GlobalAppContext.get(), getString(R.string.error_connect_to_remote, e.getMessage()), Toast.makeText(GlobalAppContext.get(), getString(R.string.error_connect_to_remote, e.getMessage()),
Toast.LENGTH_LONG).show(); Toast.LENGTH_LONG).show();