Salut à tous,
j'essaie d'optimiser un programme assez conséquent qui a quelques problèmes de lag sur une fois sur internet. avant, a chaque envoi de message on créait une nouvelle socket, on envoyait un message et on attendait de recevoir l'acquittement...
j'essaie de simplifier tout ça en séparant les méthodes d'envoi réception à l'aide d'une classe SocketHelper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
| public class SocketHelper {
private SSLSocket socket;
private String hostname;
private int port;
private int timeOut;
/**
* SocketHelper constructor for clients
* @param hostname
* @param port
* @param timeOut
*/
public SocketHelper(String hostname, int port, int timeOut){
try {
this.hostname = hostname;
this.port = port;
this.timeOut = timeOut;
// SSL Socket
SSLSocketFactory sslFact = (SSLSocketFactory) SSLSocketFactory.getDefault();
socket = (SSLSocket) sslFact.createSocket(hostname, port);
String set[] = new String[] { "SSL_RSA_WITH_NULL_MD5" };
socket.setEnabledCipherSuites(set);
socket.setReceiveBufferSize(48000);
socket.setSendBufferSize(48000);
socket.setTcpNoDelay(true);
if (timeOut != 0)
socket.setSoTimeout(timeOut);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* SocketHelper constructor for server (with accept)
* @param sslSocket
*/
public SocketHelper(SSLSocket sslSocket){
try {
this.socket = sslSocket;
this.hostname = socket.getInetAddress().getHostName();
this.port = socket.getPort();
this.timeOut = socket.getSoTimeout();
String set[] = new String[] { "SSL_RSA_WITH_NULL_MD5" };
socket.setEnabledCipherSuites(set);
socket.setReceiveBufferSize(48000);
socket.setSendBufferSize(48000);
socket.setTcpNoDelay(true);
} catch (SocketException e) {
e.printStackTrace();
}
}
/**
* Send compressed data
* @param object
* @return true if sent, else false
*/
public boolean write(Object o){
if(socket != null && socket.isConnected() && !socket.isClosed()){
try {
OutputStream os = socket.getOutputStream();
GZIPOutputStream gos = new GZIPOutputStream(os);
BufferedOutputStream bos = new BufferedOutputStream(gos);
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(o);
out.flush();
bos.flush();
gos.finish();
return true;
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
/**
* Read compressed data
* @return object
*/
public Object read(){
if(socket != null && socket.isConnected() && !socket.isClosed()){
try {
InputStream is = socket.getInputStream();
GZIPInputStream gis = new GZIPInputStream(is);
BufferedInputStream bis = new BufferedInputStream(gis);
ObjectInputStream in = new ObjectInputStream(bis);
return in.readObject();
} catch (EOFException e){
System.out.println("debug : EOF on socket : "+hostname+":"+port);
close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return null;
}
/**
* Close the socket
* @return true if closed, else false
*/
public boolean close(){
if(socket != null){
try {
socket.close();
return true;
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
/**
* Get the socket
* @return socket
*/
public Socket getSocket(){
return socket;
}
/**
* Get Remote Host Name attached to the socket
* @return hostname
*/
public String getHostname() {
return hostname;
}
/**
* Get Remote Port attached to the socket
* @return
*/
public int getPort() {
return port;
}
/**
* Get read time out (ms)
* @return timeOut
*/
public int getTimeOut() {
return timeOut;
}
/**
* Set the read time out (ms)
* @param timeOut
* @return
*/
public boolean setTimeOut(int timeOut) {
if(socket != null){
try {
socket.setSoTimeout(timeOut);
this.timeOut = timeOut;
return true;
} catch (SocketException e) {
e.printStackTrace();
}
}
return false;
}
} |
J'essaie ensuite d'utiliser la même socket pour tous les échanges, avec un gestionnaire de requêtes traitant les messages reçus. (ClientThread).
Les classes qui ont besoin d'envoyer un message le font par appel a CMCThread.getInstance.write(...) et c'est le CMCThread qui leur renvoie la réponse éventuelle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
public class CMCThread extends Thread {
private static CMCThread _instance;
private SocketHelper socketHelper;
private LoginThread loginThread;
private RealTimeThread realTimeThread;
private CMCThread(){
socketHelper = new SocketHelper(Activator.getStringVal(CMCConfigKey.Server_IP),
Integer.valueOf(Activator.getStringVal(CMCConfigKey.Server_Port)),
3000);
socketHelper.setForcedOnline(true);
}
public static CMCThread getInstance(){
if(_instance == null)
_instance = new CMCThread();
return _instance;
}
public boolean write(Object o){
return socketHelper.write(o);
}
public void setLoginThread(LoginThread lt){
this.loginThread = lt;
}
public void setRealTimeThread(RealTimeThread rt){
this.realTimeThread = rt;
}
public void run(){
while(socketHelper.getSocket() != null){
Object obj = socketHelper.read();
if(obj instanceof LoginRequest){
try {
loginThread.receiveAnswer((LoginRequest) obj);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(obj instanceof CRequest){
switch(((CRequest) obj).getType()){
case RequestConstants.AGENT_SEND_REALTIME_DATA :
try {
realTimeThread.passRequest((CRequest) obj);
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
default :
System.out.println("debug : received "+((CRequest) obj).getType());
break;
}
}
}
}
} |
Je voudrais votre avis sur tout ça, car bien que ça aie l'air de marcher, j'ai un problème qui revient assez souvent (un message sur 15/20) :
java.io.IOException: Not in GZIP format
remonté par par le socketHelper.read de mon thread et plus précisément par cette ligne dans SocketHelper : GZIPInputStream gis = new GZIPInputStream(is);
J'ai vu quelques cas similaires sur internet mais je n'ai pas réussi à enlever ce problème ( qui n'éxistait pas en créant une socket à chaque envoi de message ) . J'ai réalisé la même chose dans les autres programmes (le serveur et un autre client) qui rencontrent le même problème alors que les messages n'ont pas changé !
Merci de votre aide !
Partager