Android socket 客户端 C++服务端, 延时严重解决,贴点粘包代码

来源:互联网 发布:名著推荐 知乎 编辑:程序博客网 时间:2024/06/05 05:40

这个问题曾经困扰姐很久,但因为只是延时,而数据仍然正确,就将这个问题放在一边了。

昨天开始研究,以为是IO包没有NIO包快的原因,昨天改用NIO socket,写完一测,仍然有严重的延时呀。

姐差点傻眼,不过还好姐聪明,原来是姐缓存的数据没有全部处理掉呀,而是在等下次有数据进来的时候才处理,那些聊天消息其实早就发来了,被姐藏着呢。

哎,终于轻松了许多。

贴点代码出来现现眼吧

ps : 姐用的是google protobuf协议呦

private int dataState = 0;// 上一次收到消息后得到的状态 (初始时为 0 )private final int EQUAL = 0;//正好private final int LACK = 1;//少了private final int OVER = 2;//多了private byte[] fromLastBytes; //上次剩余的private int overLast;// 上次剩余的长度private byte[] savedBytes;// 不够,保存在lackedBytes里,等待下次传入数据后拼接private byte[] exactBytes;    // 正好的也是最终要处理的private void handleServerMessage(byte[] temp, int count) {System.out.println("***************接收服务端信息*****************  start    "  + count);//System.out.println("上次信息情况: dataState : " + dataState );////if(dataState == OVER)System.out.println("上次信息剩余: overLast        : " + overLast);//if(dataState == LACK)System.out.println("上次信息缺少 savedBytes.length : " + savedBytes.length);byte[] bytes = null;if(dataState == EQUAL) // 1:第一次有消息进来  2:本次消息之前 传入及所需相等{bytes = new byte[count];for(int i = 0; i < count; i++){bytes[i] = temp[i];}}else if (dataState == LACK) {//上次消息不够  : 上次保留的 + 本次传入的bytes = new byte[savedBytes.length + count];for(int i = 0; i<savedBytes.length; i++){bytes[i] = savedBytes[i];}for(int i = 0; i < count; i++){bytes[i + savedBytes.length] = temp[i];}savedBytes = null;}else if (dataState == OVER) {//上次消息有多余 : 上次多余的 + 本次传入的bytes = new byte[fromLastBytes.length + count];for(int i = 0 ; i < fromLastBytes.length; i++){bytes[i] = fromLastBytes[i];}for(int i = 0; i < count; i++){bytes[i + fromLastBytes.length] = temp[i];}fromLastBytes = null;}byte whole_msg_len_bytes[] = new byte[2];whole_msg_len_bytes[0] = bytes[2];whole_msg_len_bytes[1] = bytes[3];short whole_msg_len = StreamTool.byteToShort(whole_msg_len_bytes);// (2)       --->  整条信息长度(3-7)//System.out.println(" 1 + 2 + 信息 需要的长度(3-7)  : "+ (whole_msg_len + 4) );//System.out.println("经过拼接的信息长度         : " + bytes.length);//处理本次dataState = getDataState(whole_msg_len,bytes.length);//System.out.println("经过拼接后信息情况: dataState : " + dataState);if(dataState == EQUAL ){exactBytes = new byte[whole_msg_len];for(int i = 0 ; i< whole_msg_len; i++){exactBytes[i] = bytes[i + 4];}handleFinalBytes(exactBytes);}if(dataState == OVER){exactBytes = new byte[whole_msg_len];for(int i = 0 ; i< whole_msg_len; i++){exactBytes[i] = bytes[i + 4];}handleFinalBytes(exactBytes);overLast = bytes.length - whole_msg_len -4;fromLastBytes = new byte[overLast];//System.out.println("经过拼接后剩余: overLast : " + overLast);for(int i = 0; i< overLast ; i++){fromLastBytes[i] = bytes[whole_msg_len+4 +i];}handleServerMessage(null,0);  // 这句就是姐原来的困扰所在噩噩噩噩噩噩噩噩噩}if (dataState == LACK) {savedBytes = new byte[bytes.length];savedBytes = bytes.clone();}}private void handleFinalBytes(byte[] message) {  //message  已经去掉flag和标准的长度 ---- 共去掉4bytesbyte[] protocol_bytes = new byte[4];for(int i = 0 ; i < 4; i++){protocol_bytes[i] = message[i + 74];}int protocol = StreamTool.bytesToInt(protocol_bytes);System.out.println("NioSocketClient               收到服务端信息协议号: " + protocol);byte[] protobuf_length_bytes = new byte[4];for(int i = 0 ; i < 4; i++){protobuf_length_bytes[i] = message[i + 78];}int protobuf_length = StreamTool.bytesToInt(protobuf_length_bytes);byte[] protobuf_bytes = new byte[protobuf_length];for(int i = 0 ; i < protobuf_length; i++){protobuf_bytes[i] = message[i + 82];}Message respMsg = GetMessageByProtocol.getMessage(protocol, protobuf_bytes);SocketDataEvent socketDataEvent = new SocketDataEvent(this, protocol,respMsg);NioSocketClient.notifyListener(socketDataEvent);}private int getDataState(short whole_msg_len, int count) {int dataState = -1;if(whole_msg_len  + 4 == count) dataState = EQUAL;if(whole_msg_len  + 4 > count) dataState = LACK;if(whole_msg_len  + 4 < count) dataState = OVER;return dataState;}

暂时没出现错误,有错了姐再来改



以上代码有误,参考底下的

import java.io.BufferedOutputStream;import java.io.DataInputStream;import java.io.IOException;import java.net.Socket;import java.net.UnknownHostException;import java.util.ArrayList;import java.util.List;import com.chat.data.ChatRoomData;import com.chat.data.GetMessageByProtocol;import com.chat.event.SocketDataEvent;import com.chat.event.SocketDataEventListener;import com.google.protobuf.Message;import com.utils.StreamTool;public class MySocket {DataInputStream dataInputStream;BufferedOutputStream bufferedOutputStream;Socket socket;public static List<SocketDataEventListener> listeners = new ArrayList<SocketDataEventListener>();static MySocket instance;public static boolean flag;public static MySocket getInstance() {if (instance == null) {instance = new MySocket();}return instance;}public void connectMySocket(String ip, int port) {try {socket = new Socket(ip, port);flag = true;dataInputStream = new DataInputStream(socket.getInputStream());bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());new MyNewSocketReader(dataInputStream).start();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}public void closeMySocket() {try {flag = false;bufferedOutputStream.close();dataInputStream.close();socket.close();} catch (IOException e) {e.printStackTrace();}}public void addSocketDataEventListener(SocketDataEventListener listener) {listeners.add(listener);}public void removeSocketDataEventListener(SocketDataEventListener listener) {listeners.remove(listener);}public void sendMessage(byte[] msg, int protocol) {int msgSize = msg.length; // (9)'s length// int bufferlen = msgSize + 86; // (1) ~ (9)total lengthint len = msgSize + 82; // (3) ~ (9) total lengthtry {bufferedOutputStream.write(StreamTool.shortToByte((short) 0xEA));bufferedOutputStream.write(StreamTool.shortToByte((short) len));byte uuid[] = (ChatRoomData.uuid.toString()).getBytes("UTF-8");bufferedOutputStream.write(uuid);int leftSize = 64 - uuid.length;for (int i = 0; i < leftSize; i++) {bufferedOutputStream.write(0);}bufferedOutputStream.write(StreamTool.intToByte(4));bufferedOutputStream.write(StreamTool.intToByte(5));bufferedOutputStream.write(StreamTool.shortToByte((short) 6));bufferedOutputStream.write(StreamTool.intToByte(protocol));bufferedOutputStream.write(StreamTool.intToByte(msgSize));bufferedOutputStream.write(msg);bufferedOutputStream.flush();} catch (IOException e) {e.printStackTrace();}}public static void notifyListener(SocketDataEvent socketDataEvent) {for (int i = 0; i < MySocket.listeners.size(); i++) {MySocket.listeners.get(i).socketDataEvent(socketDataEvent);}}}class MyNewSocketReader extends Thread {private int dataState = 0;private final int EQUAL = 0;private final int LACK = 1;private final int OVER = 2;private byte[] exactBytes; private byte[] bufferBytes;DataInputStream dataInputStream;public MyNewSocketReader(DataInputStream dis) {this.dataInputStream = dis;}@Overridepublic void run() {while (MySocket.flag) {recvMsg(dataInputStream);}}private void recvMsg(DataInputStream inputStream) {try {if (inputStream.available() != 0) {byte input[] = new byte[inputStream.available()];int count = inputStream.read(input);if (count > -1) {addToBufferBytes(input);input = null;}}} catch (IOException e) {e.printStackTrace();} catch (NegativeArraySizeException e) {e.printStackTrace();} catch (NullPointerException e) {e.printStackTrace();}}private void addToBufferBytes(byte[] fromServer) {if(bufferBytes == null || bufferBytes.length == 0) bufferBytes = fromServer.clone();else {byte[] temp = bufferBytes.clone();bufferBytes = new byte[temp.length + fromServer.length];for(int i = 0 ; i < temp.length; i++){bufferBytes[i] = temp[i];}for(int i = 0; i< fromServer.length;i++){bufferBytes[i + temp.length] = fromServer[i];}}handleBytesFromServer();}private void handleBytesFromServer(){byte whole_msg_len_bytes[] = new byte[2];whole_msg_len_bytes[0] = bufferBytes[2];whole_msg_len_bytes[1] = bufferBytes[3];short whole_msg_len = StreamTool.byteToShort(whole_msg_len_bytes);// (2)       --->  整条信息长度(3-7)dataState = getDataState(whole_msg_len,bufferBytes.length);if(dataState == EQUAL ){exactBytes = new byte[whole_msg_len];for(int i = 0 ; i< whole_msg_len; i++){exactBytes[i] = bufferBytes[i + 4];}handleFinalBytes(exactBytes);exactBytes = null;bufferBytes = null;}if(dataState == OVER) {exactBytes = new byte[whole_msg_len];for(int i = 0 ; i< whole_msg_len; i++){exactBytes[i] = bufferBytes[i + 4];}handleFinalBytes(exactBytes);exactBytes = null;int overLast = bufferBytes.length - whole_msg_len -4;byte[] fromLastBytes = new byte[overLast];for(int i = 0; i< overLast ; i++){fromLastBytes[i] = bufferBytes[whole_msg_len+4 +i];}bufferBytes = fromLastBytes.clone();handleBytesFromServer();}}private void handleFinalBytes(byte[] message) {  byte[] protocol_bytes = new byte[4];for(int i = 0 ; i < 4; i++){protocol_bytes[i] = message[i + 74];}int protocol = StreamTool.bytesToInt(protocol_bytes);System.out.println("MySocket               收到服务端信息协议号: " + protocol);byte[] protobuf_length_bytes = new byte[4];for(int i = 0 ; i < 4; i++){protobuf_length_bytes[i] = message[i + 78];}int protobuf_length = StreamTool.bytesToInt(protobuf_length_bytes);byte[] protobuf_bytes = new byte[protobuf_length];for(int i = 0 ; i < protobuf_length; i++){protobuf_bytes[i] = message[i + 82];}Message respMsg = GetMessageByProtocol.getMessage(protocol, protobuf_bytes);SocketDataEvent socketDataEvent = new SocketDataEvent(this, protocol,respMsg);MySocket.notifyListener(socketDataEvent);}private int getDataState(short whole_msg_len, int count) {int dataState = -1;if(whole_msg_len  + 4 == count) dataState = EQUAL;if(whole_msg_len  + 4 > count) dataState = LACK;if(whole_msg_len  + 4 < count) dataState = OVER;return dataState;}}



0 0
原创粉丝点击