github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgRpc/kmgRpcJava/java/src/testPackage/RpcDemo.java (about) 1 package testPackage; 2 import com.google.gson.Gson; 3 import com.google.gson.GsonBuilder; 4 import com.google.gson.JsonDeserializationContext; 5 import com.google.gson.JsonDeserializer; 6 import com.google.gson.JsonElement; 7 import com.google.gson.JsonParseException; 8 import com.google.gson.JsonPrimitive; 9 import com.google.gson.JsonSerializationContext; 10 import com.google.gson.JsonSerializer; 11 import com.google.gson.JsonSyntaxException; 12 import javax.crypto.Cipher; 13 import javax.crypto.spec.IvParameterSpec; 14 import javax.crypto.spec.SecretKeySpec; 15 import java.io.ByteArrayOutputStream; 16 import java.io.IOException; 17 import java.io.InputStream; 18 import java.io.OutputStream; 19 import java.lang.reflect.Type; 20 import java.net.HttpURLConnection; 21 import java.net.URL; 22 import java.nio.charset.Charset; 23 import java.security.MessageDigest; 24 import java.security.SecureRandom; 25 import java.util.Arrays; 26 import java.util.Calendar; 27 import java.util.Date; 28 import java.util.List; 29 import java.util.SimpleTimeZone; 30 import java.util.TimeZone; 31 import java.util.zip.Deflater; 32 import java.util.zip.Inflater; 33 /* 34 example: 35 RpcDemo.ConfigDefaultClient("http://127.0.0.1:34567","abc psk") // added in some init function. 36 String result = RpcDemo.GetDefaultClient().PostScoreInt("abc",1) // use the rpc everywhere. 37 */ 38 public class RpcDemo { 39 //类型列表 40 private static class PostScoreIntRpcRequest{ 41 public String LbId; 42 public Integer Score; 43 } 44 public static class PostScoreIntRpcResponse{ 45 public String Info; 46 } 47 public static class DemoRequest{ 48 } 49 private static class DemoFunc2RpcRequest{ 50 public DemoRequest Req1; 51 public DemoRequest Req2; 52 } 53 private static class DemoFunc3RpcRequest{ 54 public DemoRequest Req1; 55 public DemoRequest Req2; 56 } 57 private static class DemoFunc4RpcRequest{ 58 public DemoRequest Req1; 59 public DemoRequest Req2; 60 } 61 private static class DemoFunc5RpcRequest{ 62 public DemoRequest Req1; 63 public DemoRequest Req2; 64 } 65 public static class DemoFunc5RpcResponse{ 66 public String Info; 67 } 68 private static class DemoFunc7RpcRequest{ 69 public DemoRequest Req1; 70 public DemoRequest Req2; 71 } 72 public static class DemoFunc7RpcResponse{ 73 public String Response; 74 } 75 private static class DemoFunc8RpcRequest{ 76 public DemoRequest Req1; 77 public DemoRequest Req2; 78 public Integer Req3; 79 } 80 public static class DemoFunc8RpcResponse{ 81 public String Info; 82 } 83 private static class DemoTimeRpcRequest{ 84 public Date T; 85 } 86 public static class DemoTimeRpcResponse{ 87 public Date Out; 88 } 89 private static class DemoTime2RpcRequest{ 90 public Date T; 91 } 92 public static class DemoTime2RpcResponse{ 93 public Date Out; 94 } 95 private static class DemoClientIpRpcRequest{ 96 } 97 public static class DemoClientIpRpcResponse{ 98 public String Ip; 99 } 100 public static class Client{ 101 // 所有Api列表 102 public String PostScoreInt(String LbId,Integer Score) throws Exception{ 103 PostScoreIntRpcRequest reqData = new PostScoreIntRpcRequest(); 104 reqData.LbId = LbId; 105 reqData.Score = Score; 106 return this.sendRequest("PostScoreInt", reqData, PostScoreIntRpcResponse.class).Info; 107 } 108 public void DemoFunc2(DemoRequest Req1,DemoRequest Req2) throws Exception{ 109 DemoFunc2RpcRequest reqData = new DemoFunc2RpcRequest(); 110 reqData.Req1 = Req1; 111 reqData.Req2 = Req2; 112 this.sendRequest("DemoFunc2", reqData, void.class); 113 } 114 public void DemoFunc3(DemoRequest Req1,DemoRequest Req2) throws Exception{ 115 DemoFunc3RpcRequest reqData = new DemoFunc3RpcRequest(); 116 reqData.Req1 = Req1; 117 reqData.Req2 = Req2; 118 this.sendRequest("DemoFunc3", reqData, void.class); 119 } 120 public void DemoFunc4(DemoRequest Req1,DemoRequest Req2) throws Exception{ 121 DemoFunc4RpcRequest reqData = new DemoFunc4RpcRequest(); 122 reqData.Req1 = Req1; 123 reqData.Req2 = Req2; 124 this.sendRequest("DemoFunc4", reqData, void.class); 125 } 126 public String DemoFunc5(DemoRequest Req1,DemoRequest Req2) throws Exception{ 127 DemoFunc5RpcRequest reqData = new DemoFunc5RpcRequest(); 128 reqData.Req1 = Req1; 129 reqData.Req2 = Req2; 130 return this.sendRequest("DemoFunc5", reqData, DemoFunc5RpcResponse.class).Info; 131 } 132 public String DemoFunc7(DemoRequest Req1,DemoRequest Req2) throws Exception{ 133 DemoFunc7RpcRequest reqData = new DemoFunc7RpcRequest(); 134 reqData.Req1 = Req1; 135 reqData.Req2 = Req2; 136 return this.sendRequest("DemoFunc7", reqData, DemoFunc7RpcResponse.class).Response; 137 } 138 public String DemoFunc8(DemoRequest Req1,DemoRequest Req2,Integer Req3) throws Exception{ 139 DemoFunc8RpcRequest reqData = new DemoFunc8RpcRequest(); 140 reqData.Req1 = Req1; 141 reqData.Req2 = Req2; 142 reqData.Req3 = Req3; 143 return this.sendRequest("DemoFunc8", reqData, DemoFunc8RpcResponse.class).Info; 144 } 145 public Date DemoTime(Date T) throws Exception{ 146 DemoTimeRpcRequest reqData = new DemoTimeRpcRequest(); 147 reqData.T = T; 148 return this.sendRequest("DemoTime", reqData, DemoTimeRpcResponse.class).Out; 149 } 150 public Date DemoTime2(Date T) throws Exception{ 151 DemoTime2RpcRequest reqData = new DemoTime2RpcRequest(); 152 reqData.T = T; 153 return this.sendRequest("DemoTime2", reqData, DemoTime2RpcResponse.class).Out; 154 } 155 public String DemoClientIp() throws Exception{ 156 DemoClientIpRpcRequest reqData = new DemoClientIpRpcRequest(); 157 return this.sendRequest("DemoClientIp", reqData, DemoClientIpRpcResponse.class).Ip; 158 } 159 //引入的不会变的库代码.还需要com.google.gson 这个package的依赖 160 public String RemoteUrl; 161 public byte[] Psk; 162 private <T> T sendRequest(String apiName,Object reqData,Class<T> tClass) throws Exception{ 163 String inDataString = kmgJson.MarshalToString(reqData); // UTF8? 啥编码? 164 if (apiName.length()>255){ 165 throw new Exception("len(apiName)>255"); 166 } 167 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 168 baos.write(apiName.length()); 169 baos.write(KmgString.StringToArrayByte(apiName)); 170 baos.write(KmgString.StringToArrayByte(inDataString)); 171 byte[] inByte = baos.toByteArray(); 172 if (this.Psk!=null){ 173 inByte = kmgCrypto.CompressAndEncryptBytesEncodeV2(this.Psk, inByte); 174 } 175 byte[] outBytes = kmgHttp.SimplePost(this.RemoteUrl, inByte); 176 outBytes = kmgCrypto.CompressAndEncryptBytesDecodeV2(this.Psk, outBytes); 177 if (outBytes.length==0){ 178 throw new Exception("outBytes.length==0"); 179 } 180 String AfterString = KmgString.ArrayByteToString(Arrays.copyOfRange(outBytes,1,outBytes.length)); 181 if (outBytes[0]==1){ //error 182 throw new Exception(AfterString); 183 }else if (outBytes[0]==2) { //success 184 return kmgJson.UnmarshalFromString(AfterString, tClass); 185 } 186 throw new Exception("httpjsonApi protocol error 1 "+outBytes[0]); 187 } 188 } 189 public static void ConfigDefaultClient(String RemoteUrl,String pskStr){ 190 defaultClient = new Client(); 191 defaultClient.RemoteUrl = RemoteUrl; 192 defaultClient.Psk = kmgCrypto.Get32PskFromString(pskStr); 193 } 194 private static Client defaultClient; 195 public static Client GetDefaultClient(){ 196 return defaultClient; 197 } 198 public static class KmgString{ 199 public static final Charset UTF_8 = Charset.forName("UTF-8"); 200 public static byte[] StringToArrayByte(String str){ 201 return str.getBytes(UTF_8); 202 } 203 public static String ArrayByteToString(byte[] bytes){ 204 return new String(bytes, UTF_8); 205 } 206 } 207 public static class kmgBytes { 208 public static byte[] Slice(byte[] in,int start,int end){ 209 return Arrays.copyOfRange(in,start,end); 210 } 211 } 212 public static class kmgIo { 213 private static final int EOF = -1; 214 public static byte[] InputStreamReadAll(final InputStream input) throws IOException { 215 final ByteArrayOutputStream output = new ByteArrayOutputStream(); 216 copy(input, output); 217 return output.toByteArray(); 218 } 219 public static int copy(final InputStream input, final OutputStream output) throws IOException { 220 final long count = copyLarge(input, output,new byte[8192]); 221 if (count > Integer.MAX_VALUE) { 222 return -1; 223 } 224 return (int) count; 225 } 226 public static long copyLarge(final InputStream input, final OutputStream output, final byte[] buffer) 227 throws IOException { 228 long count = 0; 229 int n = 0; 230 while (EOF != (n = input.read(buffer))) { 231 output.write(buffer, 0, n); 232 count += n; 233 } 234 return count; 235 } 236 } 237 public static class kmgHttp { 238 public static byte[] SimplePost(String urls,byte[] inByte) throws Exception{ 239 System.setProperty("http.keepAlive", "false"); 240 URL url = new URL(urls); 241 HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 242 conn.setRequestMethod("POST"); 243 conn.setRequestProperty("Content-Type", "image/jpeg"); 244 conn.setUseCaches(false); 245 conn.setDoInput(true); 246 conn.setDoOutput(true); 247 conn.setReadTimeout(10000); 248 conn.setConnectTimeout(5000); 249 OutputStream os = conn.getOutputStream(); 250 os.write(inByte); 251 os.flush(); 252 os.close(); 253 InputStream is; 254 if (conn.getResponseCode()==200){ 255 is = conn.getInputStream(); 256 }else{ 257 is = conn.getErrorStream(); 258 } 259 byte[] outByte = kmgIo.InputStreamReadAll(is); 260 is.close(); 261 return outByte; 262 } 263 } 264 public static class kmgCrypto { 265 private static byte[] magicCode4 = new byte[]{(byte)0xa7,(byte)0x97,0x6d,0x15}; 266 // key lenth 32 267 public static byte[] CompressAndEncryptBytesEncodeV2(byte[] key,byte[] data) throws Exception{ 268 data = compressV2(data); 269 byte[] cbcIv = KmgRand.MustCryptoRandBytes(16); 270 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 271 buf.write(data); 272 buf.write(magicCode4); 273 Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); 274 cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(cbcIv)); 275 byte[] encrypted = cipher.doFinal(buf.toByteArray()); 276 buf = new ByteArrayOutputStream(); 277 buf.write(cbcIv); 278 buf.write(encrypted); 279 return buf.toByteArray(); 280 } 281 // key lenth 32 282 public static byte[] CompressAndEncryptBytesDecodeV2(byte[] key,byte[] data) throws Exception { 283 if (data.length < 21) { 284 throw new Exception("[kmgCrypto.CompressAndEncryptBytesDecode] input data too small"); 285 } 286 byte[] cbcIv = kmgBytes.Slice(data, 0, 16); 287 byte[] encrypted = kmgBytes.Slice(data, 16, data.length); 288 Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); 289 cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(cbcIv)); 290 byte[] decrypted = cipher.doFinal(encrypted); 291 byte[] compressed = kmgBytes.Slice(decrypted, 0, decrypted.length - 4); 292 if (!Arrays.equals(magicCode4, kmgBytes.Slice(decrypted, decrypted.length - 4, decrypted.length))){ 293 throw new Exception("[kmgCrypto.CompressAndEncryptBytesDecode] magicCode not match"); 294 } 295 return uncompressV2(compressed); 296 } 297 private static byte[] compressV2(byte[] data) throws Exception{ 298 byte[] outData = kmgCompress.ZlibMustCompress(data); 299 if (outData.length>=data.length){ 300 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 301 buf.write(0); 302 buf.write(data); 303 return buf.toByteArray(); 304 }else{ 305 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 306 buf.write(1); 307 buf.write(outData); 308 return buf.toByteArray(); 309 } 310 } 311 private static byte[] uncompressV2(byte[] data) throws Exception{ 312 if (data.length==0){ 313 throw new Exception("[uncopressV2] len(inData)==0"); 314 } 315 if (data[0]==0){ 316 return kmgBytes.Slice(data, 1, data.length); 317 } 318 return kmgCompress.ZlibUnCompress(kmgBytes.Slice(data, 1, data.length)); 319 } 320 public static byte[] Sha512Sum(byte[] data) { 321 try { 322 MessageDigest sh = MessageDigest.getInstance("SHA-512"); 323 sh.update(data); 324 return sh.digest(); 325 }catch(Exception e){ 326 System.out.println(e.getMessage()); 327 e.printStackTrace(); 328 } 329 return null; 330 } 331 public static byte[] Get32PskFromString(String s){ 332 return kmgBytes.Slice(kmgCrypto.Sha512Sum(KmgString.StringToArrayByte(s)), 0, 32); 333 } 334 } 335 public static class kmgCompress { 336 public static byte[] ZlibMustCompress(byte[] inB){ 337 Deflater deflater = new Deflater(); 338 deflater.setInput(inB); 339 deflater.finish(); 340 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 341 byte[] buf = new byte[8192]; 342 while (!deflater.finished()) { 343 int byteCount = deflater.deflate(buf); 344 baos.write(buf, 0, byteCount); 345 } 346 deflater.end(); 347 byte[] out = baos.toByteArray(); 348 return out; 349 } 350 public static byte[] ZlibUnCompress(byte[] inB) throws Exception{ 351 Inflater deflater = new Inflater(); 352 deflater.setInput(inB); 353 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 354 byte[] buf = new byte[8192]; 355 while (!deflater.finished()) { 356 int byteCount = deflater.inflate(buf); 357 if (byteCount==0){ 358 break; 359 } 360 baos.write(buf, 0, byteCount); 361 } 362 deflater.end(); 363 return baos.toByteArray(); 364 } 365 } 366 public static class kmgSync { 367 public static class Once{ 368 private Object locker = new Object(); 369 private boolean isInit = false; 370 public void Do(Runnable f){ 371 synchronized (locker){ 372 if (isInit){ 373 return; 374 } 375 f.run(); 376 isInit = true; 377 } 378 } 379 } 380 } 381 public static class kmgJson { 382 public static String MarshalToString(Object data){ 383 return getGson().toJson(data); 384 } 385 public static<T> T UnmarshalFromString(String s,Class<T> t) throws JsonSyntaxException { 386 if (t==void.class){ 387 return null; 388 } 389 return getGson().fromJson(s,t); 390 } 391 private static Gson gson; 392 private static kmgSync.Once gsonOnce = new kmgSync.Once(); 393 private static Gson getGson(){ 394 gsonOnce.Do(new Runnable() { 395 @Override 396 public void run() { 397 JsonSerializer<Date> ser = new JsonSerializer<Date>() { 398 @Override 399 public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext 400 context) { 401 if (src == null) { 402 return null; 403 } else { 404 return new JsonPrimitive(KmgTime.FormatGolangDate(src)); 405 } 406 } 407 }; 408 JsonDeserializer<Date> deser = new JsonDeserializer<Date>() { 409 @Override 410 public Date deserialize(JsonElement json, Type typeOfT, 411 JsonDeserializationContext context) throws JsonParseException { 412 if (json == null) { 413 return null; 414 } else { 415 try { 416 return KmgTime.ParseGolangDate(json.getAsString()); 417 } catch (Exception e) { 418 throw new JsonParseException(e.getMessage()); 419 } 420 } 421 } 422 }; 423 gson = new GsonBuilder() 424 .registerTypeAdapter(Date.class, ser) 425 .registerTypeAdapter(Date.class, deser).create(); 426 } 427 }); 428 return gson; 429 } 430 } 431 public static class KmgRand{ 432 public static byte[] MustCryptoRandBytes(int length) { 433 SecureRandom sr = new SecureRandom(); 434 byte[] output = new byte[length]; 435 sr.nextBytes(output); 436 return output; 437 } 438 } 439 public static class KmgTime{ 440 public static Date ParseGolangDate(String st) throws Exception{ 441 Calendar cal = Calendar.getInstance(); 442 int year = Integer.parseInt(st.substring(0, 4)); 443 int month = Integer.parseInt(st.substring(5,7)); 444 int day = Integer.parseInt(st.substring(8,10)); 445 int hour = Integer.parseInt(st.substring(11, 13)); 446 int minute = Integer.parseInt(st.substring(14,16)); 447 int second = Integer.parseInt(st.substring(17,19)); 448 float nonaSecond = 0; 449 int tzStartPos = 19; 450 if (st.charAt(19)=='.'){ 451 // 从19开始找到第一个不是数字的字符串. 452 for (;;){ 453 tzStartPos++; 454 if (st.length()<=tzStartPos){ 455 throw new Exception("can not parse "+st); 456 } 457 char thisChar = st.charAt(tzStartPos); 458 if (thisChar>='0' && thisChar<='9'){ 459 }else{ 460 break; 461 } 462 } 463 nonaSecond = Float.parseFloat("0." + st.substring(20, tzStartPos)); 464 } 465 cal.set(Calendar.MILLISECOND,(int)(nonaSecond*1e3)); 466 char tzStart = st.charAt(tzStartPos); 467 if (tzStart=='Z'){ 468 cal.setTimeZone(TimeZone.getTimeZone("UTC")); 469 }else { 470 int tzHour = Integer.parseInt(st.substring(tzStartPos+1,tzStartPos+3)); 471 int tzMin = Integer.parseInt(st.substring(tzStartPos+4,tzStartPos+6)); 472 int tzOffset = tzHour*3600*1000 + tzMin * 60*1000; 473 if (tzStart=='-'){ 474 tzOffset = - tzOffset; 475 } 476 TimeZone tz = new SimpleTimeZone(tzOffset,""); 477 cal.setTimeZone(tz); 478 } 479 cal.set(year,month-1,day,hour,minute,second); 480 return cal.getTime(); 481 } 482 public static String FormatGolangDate(Date date){ 483 Calendar cal = Calendar.getInstance(); 484 cal.setTime(date); 485 StringBuilder buf = new StringBuilder(); 486 formatYear(cal,buf); 487 buf.append('-'); 488 formatMonth(cal, buf); 489 buf.append('-'); 490 formatDays(cal, buf); 491 buf.append('T'); 492 formatHours(cal, buf); 493 buf.append(':'); 494 formatMinutes(cal, buf); 495 buf.append(':'); 496 formatSeconds(cal,buf); 497 formatTimeZone(cal,buf); 498 return buf.toString(); 499 } 500 private static void formatYear(Calendar cal, StringBuilder buf) { 501 int year = cal.get(Calendar.YEAR); 502 String s; 503 if (year <= 0) // negative value 504 { 505 s = Integer.toString(1 - year); 506 } else // positive value 507 { 508 s = Integer.toString(year); 509 } 510 while (s.length() < 4) { 511 s = '0' + s; 512 } 513 if (year <= 0) { 514 s = '-' + s; 515 } 516 buf.append(s); 517 } 518 private static void formatMonth(Calendar cal, StringBuilder buf) { 519 formatTwoDigits(cal.get(Calendar.MONTH) + 1, buf); 520 } 521 private static void formatDays(Calendar cal, StringBuilder buf) { 522 formatTwoDigits(cal.get(Calendar.DAY_OF_MONTH), buf); 523 } 524 private static void formatHours(Calendar cal, StringBuilder buf) { 525 formatTwoDigits(cal.get(Calendar.HOUR_OF_DAY), buf); 526 } 527 private static void formatMinutes(Calendar cal, StringBuilder buf) { 528 formatTwoDigits(cal.get(Calendar.MINUTE), buf); 529 } 530 private static void formatSeconds(Calendar cal, StringBuilder buf) { 531 formatTwoDigits(cal.get(Calendar.SECOND), buf); 532 if (cal.isSet(Calendar.MILLISECOND)) { // milliseconds 533 int n = cal.get(Calendar.MILLISECOND); 534 if (n != 0) { 535 String ms = Integer.toString(n); 536 while (ms.length() < 3) { 537 ms = '0' + ms; // left 0 paddings. 538 } 539 buf.append('.'); 540 buf.append(ms); 541 } 542 } 543 } 544 /** formats time zone specifier. */ 545 private static void formatTimeZone(Calendar cal, StringBuilder buf) { 546 TimeZone tz = cal.getTimeZone(); 547 if (tz == null) { 548 return; 549 } 550 // otherwise print out normally. 551 int offset = tz.getOffset(cal.getTime().getTime()); 552 if (offset == 0) { 553 buf.append('Z'); 554 return; 555 } 556 if (offset >= 0) { 557 buf.append('+'); 558 } else { 559 buf.append('-'); 560 offset *= -1; 561 } 562 offset /= 60 * 1000; // offset is in milli-seconds 563 formatTwoDigits(offset / 60, buf); 564 buf.append(':'); 565 formatTwoDigits(offset % 60, buf); 566 } 567 /** formats Integer into two-character-wide string. */ 568 private static void formatTwoDigits(int n, StringBuilder buf) { 569 // n is always non-negative. 570 if (n < 10) { 571 buf.append('0'); 572 } 573 buf.append(n); 574 } 575 } 576 }