-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
1026 lines (900 loc) · 89.5 KB
/
atom.xml
File metadata and controls
1026 lines (900 loc) · 89.5 KB
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>HOME</title>
<link href="/atom.xml" rel="self"/>
<link href="http://flyingtime.github.io/"/>
<updated>2018-11-22T13:16:50.000Z</updated>
<id>http://flyingtime.github.io/</id>
<author>
<name>Flyingtime</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>为IOS和Android的真机和模拟器编译Luajit库</title>
<link href="http://flyingtime.github.io/2018/11/22/%E4%B8%BAIOS%E5%92%8CAndroid%E7%9A%84%E7%9C%9F%E6%9C%BA%E5%92%8C%E6%A8%A1%E6%8B%9F%E5%99%A8%E7%BC%96%E8%AF%91Luajit%E5%BA%93/"/>
<id>http://flyingtime.github.io/2018/11/22/为IOS和Android的真机和模拟器编译Luajit库/</id>
<published>2018-11-22T13:16:08.000Z</published>
<updated>2018-11-22T13:16:50.000Z</updated>
<content type="html"><![CDATA[<p>转自:<a href="http://yanfeng.life/2018/07/19/luajit-build-for-mobile/" target="_blank" rel="external">http://yanfeng.life/2018/07/19/luajit-build-for-mobile/</a></p>
<blockquote>
<p>编译 Luajit 库,的确是一个挑战。因为官网的教程,在当前版本的 Xcode 和 NDK 环境中,已经不适用了。以前只是编译了适用于真机的 Luajit 库。最近在尝试编译模拟器 Luajit 库,就顺便梳理了下 Luajit 库的编译经验,供以后查阅。网上的讨论也是有一些,但是相当一部分都已经过时。或许等你看到这篇文章的时候,可能也只是能获得一些可能的经验来解决自己的编译问题。所以说,了解一些基本的编译知识,能勉强看懂 Luajit 的 make 文件,还是很有必要的。本篇是关于 Luajit 静态库的,如果你想找的是如何编译适用于移动端的 Luajit 字节码,可以直接看 <a href="http://yanfeng.life/2018/07/11/luajit-build-latest/" target="_blank" rel="external">【最新】LuaJIT 32/64 位字节码,从编译到使用全纪录</a>。</p>
</blockquote>
<h1 id="编译环境"><a href="#编译环境" class="headerlink" title="编译环境"></a>编译环境</h1><p>等你试着自己交叉编译 Luajit 库时,就会明白环境的影响到底有多大。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line">macOS 10.13.4</div><div class="line">Xcode 9.4.1</div><div class="line">Android Studio 3.1.3</div><div class="line">先约定下基本的路径信息,供下文使用</div><div class="line">├── LuaJIT-2.1.0-beta3</div><div class="line">├── build-android.sh</div><div class="line">├── build-ios.sh</div><div class="line">├── lib</div><div class="line">│ ├── android</div><div class="line">│ │ ├── arm64-v8a</div><div class="line">│ │ ├── armeabi</div><div class="line">│ │ ├── armeabi-v7a</div><div class="line">│ │ └── x86</div><div class="line">│ └── ios</div><div class="line">│ └── libluajit2.1.0-beta.3.a</div><div class="line">``` </div><div class="line"># 编译适用于 iOS 的 Luajit 库,可能会遇到的问题</div><div class="line">## 编译前的准备</div><div class="line">需要先把 Luajit 源码的 lj_arch.h 547 行,从</div><div class="line">``` c</div><div class="line">#if LJ_TARGET_CONSOLE || (LJ_TARGET_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0)</div><div class="line">#define LJ_NO_SYSTEM 1</div><div class="line">#endif</div><div class="line">``` </div><div class="line">改为:</div><div class="line">``` c</div><div class="line">#define LJ_NO_SYSTEM 1</div><div class="line">``` </div><div class="line">否则会触发错误:</div><div class="line">``` </div><div class="line">./lib_os.c:52:14: error: 'system' is unavailable: not available on iOS</div><div class="line">`</div></pre></td></tr></table></figure></p>
<p>问题的原因大致是,此处的判断,已经在最新的 Xcode 极其编译环境中,无法争取工作。对此问题的根源感兴趣的童鞋,请自行阅读 Luajit 的 make 文件。</p>
<p><strong>注意</strong>:编译 Android 或其他平台库时,不需要修改此处源码。</p>
<h2 id="完整的-iOS-编译命令:-build-ios-sh"><a href="#完整的-iOS-编译命令:-build-ios-sh" class="headerlink" title="完整的 iOS 编译命令: build-ios.sh"></a>完整的 iOS 编译命令: build-ios.sh</h2><p>建议最好以 sh 文件的方式,直接执行,在命令行输入,可能会触发诡异的未知问题。其中一个很关键的原因是: 在复制粘贴指令时,部分文本编辑器(比如 mac 上的备忘录)会混入特殊字符,导致编译指令运行失败。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div></pre></td><td class="code"><pre><div class="line">#!/bin/bash</div><div class="line"></div><div class="line"># LuaJIT 的源码路径</div><div class="line">LUAJIT=./LuaJIT-2.1.0-beta3</div><div class="line"></div><div class="line">XCODEPATH=`xcode-select -print-path`</div><div class="line">DEVDIR=$XCODEPATH/Platforms</div><div class="line">IOSVER=iPhoneOS.sdk</div><div class="line">SIMVER=iPhoneSimulator.sdk</div><div class="line"></div><div class="line"># 库的最总名称</div><div class="line">LIBNAME=libluajit2.1.0-beta.3.a</div><div class="line"></div><div class="line"># iOS 最低兼容版本,最好与需要嵌入 LuaJIT 的 App 的最低兼容设置保持一致.</div><div class="line">MINVERSION=9.0</div><div class="line"></div><div class="line">IOSDIR=$DEVDIR/iPhoneOS.platform/Developer</div><div class="line">SIMDIR=$DEVDIR/iPhoneSimulator.platform/Developer</div><div class="line"></div><div class="line"># xctoolchain 可以使用 xcode-select --install 命令安装.</div><div class="line"># xctoolchain 和模拟器中, 目前已不包含 gcc 等命令,可以从系统其它位置复制到 $IOSBIN 目录.</div><div class="line"># 命令的具体路径,可以执行 xcodebuild -find gcc 获得.</div><div class="line">IOSBIN=$XCODEPATH/Toolchains/XcodeDefault.xctoolchain/usr/bin/</div><div class="line">SIMBIN=$SIMDIR/usr/bin/</div><div class="line"></div><div class="line">BUILD_DIR=$LUAJIT/build</div><div class="line"> </div><div class="line">rm -rf $BUILD_DIR</div><div class="line">mkdir -p $BUILD_DIR</div><div class="line">rm *.a 1>/dev/null 2>/dev/null</div><div class="line"> </div><div class="line">echo =================================================</div><div class="line">echo ARMV7 Architecture</div><div class="line">ISDKF="-arch armv7 -isysroot $IOSDIR/SDKs/$IOSVER -miphoneos-version-min=$MINVERSION"</div><div class="line">make -j -C $LUAJIT HOST_CC="gcc -m32 " CROSS=$IOSBIN TARGET_FLAGS="$ISDKF" TARGET=armv7 TARGET_SYS=iOS clean</div><div class="line">make -j -C $LUAJIT HOST_CC="gcc -m32 " CROSS=$IOSBIN TARGET_FLAGS="$ISDKF" TARGET=armv7 TARGET_SYS=iOS </div><div class="line">mv $LUAJIT/src/libluajit.a $BUILD_DIR/libluajitA7.a</div><div class="line"> </div><div class="line">echo =================================================</div><div class="line">echo ARM64 Architecture</div><div class="line">ISDKF="-arch arm64 -isysroot $IOSDIR/SDKs/$IOSVER -miphoneos-version-min=$MINVERSION"</div><div class="line">make -j -C $LUAJIT HOST_CC="gcc " CROSS=$IOSBIN TARGET_FLAGS="$ISDKF" TARGET=arm64 TARGET_SYS=iOS clean</div><div class="line">make -j -C $LUAJIT HOST_CC="gcc " CROSS=$IOSBIN TARGET_FLAGS="$ISDKF" TARGET=arm64 TARGET_SYS=iOS </div><div class="line">mv $LUAJIT/src/libluajit.a $BUILD_DIR/libluajit64bit.a</div><div class="line"> </div><div class="line">echo =================================================</div><div class="line">echo IOS Simulator Architecture</div><div class="line">ISDKF="-arch x86_64 -isysroot $SIMDIR/SDKs/$SIMVER -miphoneos-version-min=$MINVERSION"</div><div class="line">make -j -C $LUAJIT HOST_CFLAGS="-arch x86_64" HOST_LDFLAGS="-arch x86_64" TARGET_SYS=iOS TARGET=x86_64 clean</div><div class="line">make -j -C $LUAJIT HOST_CFLAGS="-arch x86_64" HOST_LDFLAGS="-arch x86_64" TARGET_SYS=iOS TARGET=x86_64 amalg CROSS=$SIMBIN TARGET_FLAGS="$ISDKF"</div><div class="line"> </div><div class="line"> </div><div class="line">mv $LUAJIT/src/libluajit.a $BUILD_DIR/libluajitx86_64.a</div><div class="line"> </div><div class="line">libtool -o $BUILD_DIR/$LIBNAME $BUILD_DIR/*.a 2> /dev/null</div><div class="line"></div><div class="line">mkdir -p $BUILD_DIR/Headers</div><div class="line">cp $LUAJIT/src/lua.h $BUILD_DIR/Headers</div><div class="line">cp $LUAJIT/src/lauxlib.h $BUILD_DIR/Headers</div><div class="line">cp $LUAJIT/src/lualib.h $BUILD_DIR/Headers</div><div class="line">cp $LUAJIT/src/luajit.h $BUILD_DIR/Headers</div><div class="line">cp $LUAJIT/src/lua.hpp $BUILD_DIR/Headers</div><div class="line">cp $LUAJIT/src/luaconf.h $BUILD_DIR/Headers</div><div class="line"> </div><div class="line">mv $BUILD_DIR/$LIBNAME ./lib/ios</div><div class="line">rm -rf $BUILD_DIR</div><div class="line"></div><div class="line">cd $LUAJIT</div><div class="line">make clean</div><div class="line">cd ..</div><div class="line">``` </div><div class="line">编译脚本运行方法:</div></pre></td></tr></table></figure></p>
<p>chmod a+x build-ios.sh<br>./build-ios.sh<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">其他可能遇到的问题</div><div class="line">/Applications/Xcode.app/Contents/Developer/Platforms/Toolchains/XcodeDefault.xctoolchain/usr/bin/gcc command not found</div><div class="line">1. 先安装 toolchains:</div></pre></td></tr></table></figure></p>
<p>xcode-select –install<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">2. 找下缺失本机上对应命令的真实路径:</div></pre></td></tr></table></figure></p>
<p>xcodebuild -find gcc</p>
<pre><code>3. 如果能找到,就把命令复制到缺失命令的位置;如果本机找不到,就从网上搜下安装教程。
## 针对模拟器的额外设置
由于iphone5s以上虚拟机需要x86_64支持,luajit为了支持此模式需要在other linker flags中增加参数(注意,只需要对模拟器添加参数,针对ios不能添加,否则apple不会通过审核):
-pagezero_size 10000 -image_base 100000000
网上类似的描述很多,也很准确,我想补充的是:最好只在 Debug 模式下的配置中增加上述特殊参数。
另外,如果你已经在使用 Luajit 的字节码,请注意模拟器 Luajit 库,需要加载的是 32 位字节码。
# 编译适用于 Android 的 Luajit 库,可能会遇到的问题
## 完整的 Android 编译命令: build-android.sh
``` shell
#!/bin/bash
# LuaJIT 的源码路径
LUAJIT=./LuaJIT-2.1.0-beta3
cd $LUAJIT
#编译 android-x86
make clean
NDK=~/library/android/sdk/ndk-bundle
NDKABI=17
NDKTRIPLE=x86
NDKVER=$NDK/toolchains/$NDKTRIPLE-4.9
NDKP=$NDKVER/prebuilt/darwin-x86_64/bin/i686-linux-android-
NDKF="-isystem $NDK/sysroot/usr/include/i686-linux-android -D__ANDROID_API__=$NDKABI -D_FILE_OFFSET_BITS=32"
NDK_SYSROOT_BUILD=$NDK/sysroot
NDK_SYSROOT_LINK=$NDK/platforms/android-$NDKABI/arch-x86
make HOST_CC="gcc-4.9 -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF" TARGET_SYS=Linux TARGET_SHLDFLAGS="--sysroot $NDK_SYSROOT_LINK" TARGET_LDFLAGS="--sysroot $NDK_SYSROOT_LINK" TARGET_CFLAGS="--sysroot $NDK_SYSROOT_BUILD"
mv ./src/libluajit.a "../lib/android/x86/libluajit.a"
#编译 android-armeabi
make clean
NDK=~/Library/Android/sdk/ndk-bundle
NDKABI=17
NDKTRIPLE=arm-linux-androideabi
NDKVER=$NDK/toolchains/$NDKTRIPLE-4.9
NDKP=$NDKVER/prebuilt/darwin-x86_64/bin/$NDKTRIPLE-
NDKF="-isystem $NDK/sysroot/usr/include/$NDKTRIPLE -D__ANDROID_API__=$NDKABI -D_FILE_OFFSET_BITS=32"
NDK_SYSROOT_BUILD=$NDK/sysroot
NDK_SYSROOT_LINK=$NDK/platforms/android-$NDKABI/arch-arm
make HOST_CC="gcc-4.9 -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF" TARGET_SYS=Linux TARGET_SHLDFLAGS="--sysroot $NDK_SYSROOT_LINK" TARGET_LDFLAGS="--sysroot $NDK_SYSROOT_LINK" TARGET_CFLAGS="--sysroot $NDK_SYSROOT_BUILD"
mv ./src/libluajit.a ../lib/android/armeabi/libluajit.a
#编译 android-armeabi-v7a
make clean
NDK=~/Library/Android/sdk/ndk-bundle
NDKABI=17
NDKTRIPLE=arm-linux-androideabi
NDKVER=$NDK/toolchains/$NDKTRIPLE-4.9
NDKP=$NDKVER/prebuilt/darwin-x86_64/bin/$NDKTRIPLE-
NDKF="-isystem $NDK/sysroot/usr/include/$NDKTRIPLE -D__ANDROID_API__=$NDKABI -D_FILE_OFFSET_BITS=32"
NDK_SYSROOT_BUILD=$NDK/sysroot
NDK_SYSROOT_LINK=$NDK/platforms/android-$NDKABI/arch-arm
NDKARCH="-march=armv7-a -mfloat-abi=softfp -Wl,--fix-cortex-a8"
make HOST_CC="gcc-4.9 -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF $NDKARCH" TARGET_SYS=Linux TARGET_SHLDFLAGS="--sysroot $NDK_SYSROOT_LINK" TARGET_LDFLAGS="--sysroot $NDK_SYSROOT_LINK" TARGET_CFLAGS="--sysroot $NDK_SYSROOT_BUILD"
mv ./src/libluajit.a ../lib/android/armeabi-v7a/libluajit.a
#编译 android-arm64-v8a
make clean
NDK=~/Library/Android/sdk/ndk-bundle
NDKABI=21
NDKTRIPLE=aarch64-linux-android
NDKVER=$NDK/toolchains/$NDKTRIPLE-4.9
NDKP=$NDKVER/prebuilt/darwin-x86_64/bin/$NDKTRIPLE-
NDKF="-isystem $NDK/sysroot/usr/include/$NDKTRIPLE -D__ANDROID_API__=$NDKABI"
NDK_SYSROOT_BUILD=$NDK/sysroot
NDK_SYSROOT_LINK=$NDK/platforms/android-$NDKABI/arch-arm64
make HOST_CC="gcc-4.9" CROSS=$NDKP TARGET_FLAGS="$NDKF" TARGET_SYS=Linux TARGET_SHLDFLAGS="--sysroot $NDK_SYSROOT_LINK" TARGET_LDFLAGS="--sysroot $NDK_SYSROOT_LINK" TARGET_CFLAGS="--sysroot $NDK_SYSROOT_BUILD"
mv ./src/libluajit.a ../lib/android/arm64-v8a/libluajit.a
make clean
</code></pre><p>注意:此处共编译了 arm64-v8a,armeabi-v7a,armeabi,x86 四种CPU架构的库。其中 arm64-v8a 并没有使用,因为它会引起诡异的兼容适配问题。初步怀疑和不同厂商魔改 ROM 实现有关。期待看到小伙伴们的进一步深入解读~</p>
<h1 id="参考文章:"><a href="#参考文章:" class="headerlink" title="参考文章:"></a>参考文章:</h1><p><a href="https://github.com/rampantpixels/lua_lib/blob/master/lua/luajit/build-ios.sh" target="_blank" rel="external">https://github.com/rampantpixels/lua_lib/blob/master/lua/luajit/build-ios.sh</a></p>
<p><a href="https://github.com/cailei/luajit/blob/master/build-luajit-ios.sh" target="_blank" rel="external">https://github.com/cailei/luajit/blob/master/build-luajit-ios.sh</a></p>
<p><a href="https://blog.csdn.net/dragoncheng/article/details/43482109" target="_blank" rel="external">https://blog.csdn.net/dragoncheng/article/details/43482109</a></p>
<p><a href="https://www.cnblogs.com/HemJohn/p/5429041.html" target="_blank" rel="external">https://www.cnblogs.com/HemJohn/p/5429041.html</a></p>
<p><a href="https://www.jianshu.com/p/308d7be8b8df" target="_blank" rel="external">https://www.jianshu.com/p/308d7be8b8df</a></p>
<p><a href="https://stackoverflow.com/a/12228575" target="_blank" rel="external">https://stackoverflow.com/a/12228575</a></p>
<p><a href="http://www.codexiu.cn/android/blog/14563/" target="_blank" rel="external">http://www.codexiu.cn/android/blog/14563/</a></p>
<p><a href="https://github.com/twilio/twilio-boost-build/issues/1" target="_blank" rel="external">https://github.com/twilio/twilio-boost-build/issues/1</a></p>
]]></content>
<summary type="html">
<p>转自:<a href="http://yanfeng.life/2018/07/19/luajit-build-for-mobile/" target="_blank" rel="external">http://yanfeng.life/2018/07/19/luajit
</summary>
</entry>
<entry>
<title>Luajit位字节码,从编译到使用全纪录</title>
<link href="http://flyingtime.github.io/2018/11/22/Luajit%E4%BD%8D%E5%AD%97%E8%8A%82%E7%A0%81%EF%BC%8C%E4%BB%8E%E7%BC%96%E8%AF%91%E5%88%B0%E4%BD%BF%E7%94%A8%E5%85%A8%E7%BA%AA%E5%BD%95/"/>
<id>http://flyingtime.github.io/2018/11/22/Luajit位字节码,从编译到使用全纪录/</id>
<published>2018-11-22T13:07:04.000Z</published>
<updated>2018-11-22T13:09:30.000Z</updated>
<content type="html"><![CDATA[<p>转自:<a href="http://yanfeng.life/2018/07/11/luajit-build-latest/" target="_blank" rel="external">http://yanfeng.life/2018/07/11/luajit-build-latest/</a></p>
<blockquote>
<p>网上关于 LuaJIT 的讨论,已经显得有些陈旧。如果你对 LuaJIT 编译 Lua 源文件为具体的 32位或64位字节码,极其具体使用感兴趣的话,不妨快速读一下这篇文章。此文章针对尝试在 iOS 或 Android 上使用 LuaJIT 的小伙伴。限于篇幅,此处假定,你可以成功在 iOS/Android App 中集成了 LuaJIT,并且已经可以执行源码形式的 Lua 文件。<br>我忍不住在开头插一句: LuaJIT 编译后,只有约 600k,可能也就是一张图片的空间,但却可以让你的你App可以拥有一门完整的脚本语言的能力 – 真的很酷!为许多问题,提供了许多新的思路,特别是 App 地动态性和可配置型方面。</p>
</blockquote>
<h1 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h1><p>操作系统: macOS 10.13.4 【Linux 系统上,应该使用;Windows 系统上,仅供参考】</p>
<p>LuaJIT 版本: LuaJIT-2.1.0-beta3【官网最新版】</p>
<h1 id="目录结构预定义"><a href="#目录结构预定义" class="headerlink" title="目录结构预定义"></a>目录结构预定义</h1><p>为了便于下文指令的说明,此处简单约定下目录结构。实际使用时,按需设置和整理即可。</p>
<p>tools:存放各种编译脚本和工具。<br>source:存放编译前的 Lua 源码。以后所有的 Lua 源码,都需要放在且只能放在此文件夹下。<br>output: 用于存放编译后的 Lua 字节码文件。</p>
<h1 id="编译加密工具"><a href="#编译加密工具" class="headerlink" title="编译加密工具"></a>编译加密工具</h1><p>Lua 的加密工具,本质上就是 Lua 的解释器。此处使用的解释器源码是 LuaJIT。LuaJIT 执行效率最高,且编译出来的字节码无法逆向为 Lua 源码,更能保证源码安全性。LuaJIT 支持交叉编译,即可以在电脑上编译出 iOS 或 Android 手机上系统需要的字节码。如此,我们只需要编译一次 32 和 64 位的 LuaJIT 解释器各一个,备份存档,后续可直接使用。</p>
<p>编译 LuaJIT 解释器,直接用官方的推荐指令即可。比较特殊的一点时,如果是想编译出 64 位 LuaJIT,需要加上参数 CFLAGS=-DLUAJIT_ENABLE_GC6。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"># cd 到 LuaJIT 源码目录</div><div class="line">cd tools/LuaJIT-2.1.0-beta3</div><div class="line"># 编译 32 位 LuaJIT 解释器</div><div class="line">make clean && make && cp src/luajit ../luajit-32 && make clean</div><div class="line"># 编译 64 位 LuaJIT 解释器</div><div class="line">make clean && make CFLAGS=-DLUAJIT_ENABLE_GC64 && cp src/luajit ../luajit-64 && make clean</div></pre></td></tr></table></figure></p>
<p>注意:重新解压源码后,可能需要重新启动命令行/终端,来清除可能的系统缓存,才能正确 build 出想要的东西。</p>
<h1 id="加密-Lua-源文件"><a href="#加密-Lua-源文件" class="headerlink" title="加密 Lua 源文件"></a>加密 Lua 源文件</h1><p>所谓的加密 Lua 源文件,其实就是把 Lua 源文件,编译为 LuaJIT 字节码。相对于 Luac ,LuaJIT 字节码执行效率更高,而且无法被直接逆向为对应的 Lua 源码。</p>
<p>编译字节码,用的是 -b 命令,需要注意的是,一定要使用对应字节的 LuaJIT 解释器来编译,否则 iOS/Android App 中,可能无法加载。</p>
<p>编译后的字节码文件的后缀,可以根据自己需要自定义。此处我使用的是 “.yan” 和 “.yan64”。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"># 编译32位字节码 ,适用于Android全部手机,部分 iOS 手机。</div><div class="line">./tools/luajit-32 -b ./source/main.lua ./output/main.yan</div><div class="line"># 编译64位字节码,仅用于部分 iOS 手机。</div><div class="line">./tools/luajit-64 -b ./source/main.lua ./output/main.yan64</div></pre></td></tr></table></figure></p>
<p>注意: 敏感信息,不要直接以常量字符串的形式使用。</p>
<h1 id="在-iOS-中,根据不同的-CPU,-加载不同的字节码。"><a href="#在-iOS-中,根据不同的-CPU,-加载不同的字节码。" class="headerlink" title="在 iOS 中,根据不同的 CPU, 加载不同的字节码。"></a>在 iOS 中,根据不同的 CPU, 加载不同的字节码。</h1><p>在 Android 手机上,一般只需要使用 32 位的 LuaJIT 字节码文件即可。iOS 上,情况比较复杂,从 iOS11 之后,iOS 要求相对的库必须有64位版本。也就意味着,如果 App 想兼容 iPhone5s 以前的 32位CPU的设备的话,就必须在项目中同时放置32位和64位的LuaJIT静态库。关于适用于手机端的 LuaJIT 静态库的编译问题,暂不进一步展开。此处只讨论,如何在 iOS 中,动态根据需要准确加载对应的 32 或 64 位的 LuaJIT 字节码文件。</p>
<p>基于上文的讨论,此处给出一个简单的策略:</p>
<p>Lua 源文件,同时编译生成32位和64位字节码的文件。<br>编译后的字节码文件,仅文件后缀不同,文件路径的其他部分保证是完全一致的。如 main.yan 和 main.yan64 是由 main.lua编译得到。<br>在 iOS App 运行时,动态根据当前真正运行的是 32 还是 64 位的 LuaJIT 解释器,来选择对应的字节码文件后缀即可。<br>分享一个 swift 版的实现:<br><figure class="highlight swift"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">func</span> <span class="title">luaFileSuffix</span><span class="params">()</span></span> -> <span class="type">String</span>{</div><div class="line"> #<span class="keyword">if</span> (arch(i386) || arch(arm))</div><div class="line"> <span class="keyword">return</span> <span class="string">".yan"</span></div><div class="line"> #<span class="keyword">else</span></div><div class="line"> <span class="keyword">return</span> <span class="string">".yan64"</span></div><div class="line"> #endif</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h1 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h1><p><a href="https://stackoverflow.com/questions/18861046/how-to-determine-if-compiling-for-64-bit-ios-in-xcode" target="_blank" rel="external">How to determine if compiling for 64-bit iOS in Xcode</a></p>
<p><a href="http://luajit.org/running.html" target="_blank" rel="external">Running LuaJIT</a></p>
<p><a href="http://luajit.org/running.html" target="_blank" rel="external">Cross-compiling LuaJIT 部分很值得读</a></p>
]]></content>
<summary type="html">
<p>转自:<a href="http://yanfeng.life/2018/07/11/luajit-build-latest/" target="_blank" rel="external">http://yanfeng.life/2018/07/11/luajit-bui
</summary>
</entry>
<entry>
<title>MacOs自己动手编译Lantern 2.2.5</title>
<link href="http://flyingtime.github.io/2016/11/10/MacOs%E8%87%AA%E5%B7%B1%E5%8A%A8%E6%89%8B%E7%BC%96%E8%AF%91Lantern-2-2-5/"/>
<id>http://flyingtime.github.io/2016/11/10/MacOs自己动手编译Lantern-2-2-5/</id>
<published>2016-11-10T05:34:54.000Z</published>
<updated>2016-11-10T06:28:24.000Z</updated>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><blockquote>
<p>Lantern(蓝灯)一直是我翻墙的好伙伴,可是自从升级到macOS Sierra(10.12.1)之后,Lantern就会出现闪退的现象;而升级Lantern的版本的话,每个月就只有800M的流量。。。不该升级啊,手贱了,痛定思痛,还是想办法解决吧。。。既然Lantern是开源的那我们就自己编译试试。</p>
</blockquote>
<h3 id="动手"><a href="#动手" class="headerlink" title="动手"></a>动手</h3><ol>
<li><p>查看golang版本,当前go版本为1.7.3,如果不是最新版的话更新一下:</p>
<pre><code class="shell">brew update
brew install go
</code></pre>
</li>
<li><p>下载Lantern:</p>
<pre><code class="shell">git clone https://github.com/getlantern/lantern
</code></pre>
<p>Lantern比较大,我这里下载多次失败,那么git有没有断点续传的功能呢:</p>
<pre><code class="shell">git fetch git@github.com:getlantern/lantern.git
中途掉线后可以重复上面的命令
git checkout FETCH_HEAD
</code></pre>
</li>
<li><p>进入到Lantern目录并编译</p>
<pre><code class="shell">cd lantern
make package-darwin VERSION='2.2.5'
</code></pre>
<p>运行时按照上面的提示安装所需要的库,同时因为go版本的原因,http.Transport的定义有变化,直接把出现错误的行注释掉即可。<br>lantern/src/github.com/getlantern/flashlight/proxied/proxied.go,391行:</p>
<pre><code class="go"><span class="comment">// chained creates an http.RoundTripper. If rootCA is specified, the</span>
<span class="comment">// RoundTripper will validate the server's certificate on TLS connections</span>
<span class="comment">// against that RootCA. If persistent is specified, the RoundTripper will use</span>
<span class="comment">// keepalive connections across requests.</span>
<span class="function"><span class="keyword">func</span> <span class="title">chained</span><span class="params">(rootCA <span class="keyword">string</span>, persistent <span class="keyword">bool</span>)</span> <span class="params">(http.RoundTripper, error)</span></span> {
tr := &http.Transport{
Dial: (&net.Dialer{
Timeout: <span class="number">60</span> * time.Second,
KeepAlive: <span class="number">30</span> * time.Second,
}).Dial,
TLSHandshakeTimeout: <span class="number">10</span> * time.Second,
<span class="comment">// This method is typically used for creating a one-off HTTP client</span>
<span class="comment">// that we don't want to keep around for future calls, making</span>
<span class="comment">// persistent connections a potential source of file descriptor</span>
<span class="comment">// leaks. Note the name of this variable is misleading -- it would</span>
<span class="comment">// be clearer to call it DisablePersistentConnections -- i.e. it has</span>
<span class="comment">// nothing to do with TCP keep alives along the lines of the KeepAlive</span>
<span class="comment">// variable in net.Dialer.</span>
DisableKeepAlives: !persistent,
TLSClientConfig: &tls.Config{
<span class="comment">// Cache TLS sessions for faster connection</span>
ClientSessionCache: clientSessionCache,
},
}
<span class="comment">//if persistent {</span>
<span class="comment">// tr.MaxIdleTime = 30 * time.Second</span>
<span class="comment">// tr.EnforceMaxIdleTime()</span>
<span class="comment">//}</span>
<span class="keyword">if</span> rootCA != <span class="string">""</span> {
caCert, err := keyman.LoadCertificateFromPEMBytes([]<span class="keyword">byte</span>(rootCA))
<span class="keyword">if</span> err != <span class="literal">nil</span> {
<span class="keyword">return</span> <span class="literal">nil</span>, errors.Wrap(err).Op(<span class="string">"DecodeRootCA"</span>)
}
tr.TLSClientConfig.RootCAs = caCert.PoolContainingCert()
}
tr.Proxy = <span class="function"><span class="keyword">func</span><span class="params">(req *http.Request)</span> <span class="params">(*url.URL, error)</span></span> {
proxyAddr, ok := getProxyAddr()
<span class="keyword">if</span> !ok {
<span class="keyword">return</span> <span class="literal">nil</span>, errors.New(ErrChainedProxyUnavailable)
}
<span class="keyword">return</span> url.Parse(<span class="string">"http://"</span> + proxyAddr)
}
<span class="keyword">return</span> AsRoundTripper(<span class="function"><span class="keyword">func</span><span class="params">(req *http.Request)</span> <span class="params">(*http.Response, error)</span></span> {
op := ops.Begin(<span class="string">"chained"</span>).ProxyType(ops.ProxyChained).Request(req)
<span class="keyword">defer</span> op.End()
resp, err := tr.RoundTrip(req)
op.Response(resp)
<span class="keyword">return</span> resp, errors.Wrap(err)
}), <span class="literal">nil</span>
}
</code></pre>
<p>lantern/src/github.com/getlantern/flashlight/client/reverseproxy.go,20行:</p>
<pre><code class="go"><span class="comment">// newReverseProxy creates a reverse proxy that uses the client's balancer to</span>
<span class="comment">// dial out.</span>
<span class="function"><span class="keyword">func</span> <span class="params">(client *Client)</span> <span class="title">newReverseProxy</span><span class="params">()</span> *<span class="title">httputil</span>.<span class="title">ReverseProxy</span></span> {
transport := &http.Transport{
TLSHandshakeTimeout: <span class="number">40</span> * time.Second,
<span class="comment">//MaxIdleTime: 30 * time.Second,</span>
}
<span class="comment">//transport.EnforceMaxIdleTime()</span>
<span class="comment">// <span class="doctag">TODO:</span> would be good to make this sensitive to QOS, which</span>
<span class="comment">// right now is only respected for HTTPS connections. The</span>
<span class="comment">// challenge is that ReverseProxy reuses connections for</span>
<span class="comment">// different requests, so we might have to configure different</span>
<span class="comment">// ReverseProxies for different QOS's or something like that.</span>
transport.Dial = client.proxiedDialer(bal.Dial)
onRequest := bal.OnRequest
<span class="keyword">return</span> &httputil.ReverseProxy{
<span class="comment">// We need to set the authentication tokens for all servers that we might</span>
<span class="comment">// connect to because we don't know which one the dialer will actually</span>
<span class="comment">// pick. We also need to strip out X-Forwarded-For that reverseproxy adds</span>
<span class="comment">// because it confuses the upstream servers with the additional 127.0.0.1</span>
<span class="comment">// field when upstream servers are trying to determine the client IP.</span>
<span class="comment">// We need to add also the X-Lantern-Device-Id field.</span>
Director: <span class="function"><span class="keyword">func</span><span class="params">(req *http.Request)</span></span> {
<span class="comment">// Add back the Host header which was stripped by the ReverseProxy. This</span>
<span class="comment">// is needed for sites that do virtual hosting.</span>
req.Header.Set(<span class="string">"Host"</span>, req.Host)
onRequest(req)
},
Transport: &bandwidthTrackingRoundTripper{
&errorRewritingRoundTripper{
&noForwardedForRoundTripper{withDumpHeaders(<span class="literal">false</span>, transport)},
},
},
<span class="comment">// Set a FlushInterval to prevent overly aggressive buffering of</span>
<span class="comment">// responses, which helps keep memory usage down</span>
FlushInterval: <span class="number">250</span> * time.Millisecond,
ErrorLog: log.AsStdLogger(),
}
}
</code></pre>
<p>在编译时还会出现一个错误:<strong>“The specified item could not be found in the keychain.”</strong>,我们不管它,我们又不发布这个程序只是自己用而已,这个错误可以直接略过,这样在我们的目录里面生成Lantern.app,直接拖到Applications目录即可。</p>
</li>
</ol>
<h3 id="结果"><a href="#结果" class="headerlink" title="结果"></a>结果</h3><p>测试了一下,不会出现闪退的现象,而且依旧可以翻墙。<br><img src="/res/lantern2.2.5.png" alt=""><br><img src="/res/youtube.png" alt=""><br>通过这次实践,让我更加清楚的了解到什么叫<strong>自己动手丰衣足食</strong>了。</p>
<h3 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h3><p><a href="https://github.com/getlantern/lantern" target="_blank" rel="external">https://github.com/getlantern/lantern</a><br><a href="https://github.com/getlantern/lantern/blob/devel/README-release.md" target="_blank" rel="external">https://github.com/getlantern/lantern/blob/devel/README-release.md</a></p>
]]></content>
<summary type="html">
<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><blockquote>
<p>Lantern(蓝灯)一直是我翻墙的好伙伴,可是自从升级到macOS Sierra(10.12.1)之后,Lant
</summary>
<category term="golang" scheme="http://flyingtime.github.io/tags/golang/"/>
<category term="lantern" scheme="http://flyingtime.github.io/tags/lantern/"/>
</entry>
<entry>
<title>C# Interface的继承</title>
<link href="http://flyingtime.github.io/2016/11/03/C-Interface%E7%9A%84%E7%BB%A7%E6%89%BF/"/>
<id>http://flyingtime.github.io/2016/11/03/C-Interface的继承/</id>
<published>2016-11-03T00:35:06.000Z</published>
<updated>2016-11-03T07:33:14.000Z</updated>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><blockquote>
<p>C#的Interface讲的地方也不少,可以参考MSDN中<a href="https://msdn.microsoft.com/en-us/library/ms173156.aspx" target="_blank" rel="external">Interface</a>的介绍,再这里也不赘述,但是在翻代码的时候发现了一个问题 <strong>IList<t> : ICollection<t>, IEnumerable<t>, IEnumerable</t></t></t></strong>,这。。。是要颠覆我对接口继承的认知啊。。。到底怎么回事呢?如果你也有同样的疑问,那就让我们一起来看看吧</p>
</blockquote>
<h3 id="问题发掘"><a href="#问题发掘" class="headerlink" title="问题发掘"></a>问题发掘</h3><p>在VS 2015中新建一个console项目然后添加以下代码</p>
<pre><code class="csharp"><span class="keyword">using</span> System;
<span class="keyword">using</span> System.Collections.Generic;
<span class="keyword">using</span> System.Linq;
<span class="keyword">using</span> System.Threading.Tasks;
<span class="keyword">namespace</span> <span class="title">InterfaceTest</span>
{
<span class="keyword">public</span> <span class="keyword">interface</span> <span class="title">IA</span>
{
<span class="function"><span class="keyword">void</span> <span class="title">testA</span>(<span class="params"></span>)</span>;
}
<span class="keyword">public</span> <span class="keyword">interface</span> <span class="title">IB</span> : <span class="title">IA</span>
{
<span class="function"><span class="keyword">void</span> <span class="title">testB</span>(<span class="params"></span>)</span>;
}
<span class="keyword">public</span> <span class="keyword">interface</span> <span class="title">IC</span> : <span class="title">IB</span>
{
<span class="function"><span class="keyword">void</span> <span class="title">testC</span>(<span class="params"></span>)</span>;
}
<span class="keyword">public</span> <span class="keyword">class</span> <span class="title">Program</span>
{
<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Main</span>(<span class="params"><span class="keyword">string</span>[] args</span>)
</span>{
Console.WriteLine(<span class="string">"hello interface"</span>);
}
}
}
</code></pre>
<p>我们用反编译工具或者Reflection测试一下IC接口的相关信息<br><img src="/res/interface_ilspy.png" alt=""><br>看到问题没有?<br>我们在代码中只写的IC:IB,但是在ILSpy中得到的结果是IC:IB,IA<br>我们使用Relection试试结果:</p>
<pre><code class="csharp"><span class="keyword">using</span> System;
<span class="keyword">using</span> System.Collections.Generic;
<span class="keyword">using</span> System.Linq;
<span class="keyword">using</span> System.Threading.Tasks;
<span class="keyword">namespace</span> <span class="title">InterfaceTest</span>
{
<span class="keyword">public</span> <span class="keyword">interface</span> <span class="title">IA</span>
{
<span class="function"><span class="keyword">void</span> <span class="title">testA</span>(<span class="params"></span>)</span>;
}
<span class="keyword">public</span> <span class="keyword">interface</span> <span class="title">IB</span> : <span class="title">IA</span>
{
<span class="function"><span class="keyword">void</span> <span class="title">testB</span>(<span class="params"></span>)</span>;
}
<span class="keyword">public</span> <span class="keyword">interface</span> <span class="title">IC</span> : <span class="title">IB</span>
{
<span class="function"><span class="keyword">void</span> <span class="title">testC</span>(<span class="params"></span>)</span>;
}
<span class="keyword">public</span> <span class="keyword">class</span> <span class="title">Program</span>
{
<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Main</span>(<span class="params"><span class="keyword">string</span>[] args</span>)
</span>{
Type t = <span class="keyword">typeof</span>(IC);
<span class="keyword">foreach</span> (<span class="keyword">var</span> x <span class="keyword">in</span> t.GetInterfaces())
{
Console.WriteLine(x.Name);
}
Console.WriteLine(<span class="string">"hello interface"</span>);
Console.ReadKey();
}
}
}
</code></pre>
<p>输出:</p>
<blockquote>
<p>IB<br>IA<br>hello interface</p>
</blockquote>
<p>在goolge中搜索相关问题,终于找到一个:<a href="http://stackoverflow.com/questions/1023375/why-collections-classes-in-c-sharp-like-arraylist-inherit-from-multiple-interf" target="_blank" rel="external">http://stackoverflow.com/questions/1023375/why-collections-classes-in-c-sharp-like-arraylist-inherit-from-multiple-interf</a></p>
<h3 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h3><p>我们在写interface的继承时,只需要写继承的父接口即可,不需要写父接口所继承的接口;当然,写了也不会出错。在引用其它程序集的时候interface会列出所有的父接口信息,包括父接口的父接口。。。应该是为了让人一目了然吧,不需要再去翻父接口到底有没有继承接口。</p>
<h3 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h3><p><a href="http://stackoverflow.com/questions/1023375/why-collections-classes-in-c-sharp-like-arraylist-inherit-from-multiple-interf" target="_blank" rel="external">http://stackoverflow.com/questions/1023375/why-collections-classes-in-c-sharp-like-arraylist-inherit-from-multiple-interf</a><br><a href="https://msdn.microsoft.com/en-us/library/ms173156.aspx" target="_blank" rel="external">https://msdn.microsoft.com/en-us/library/ms173156.aspx</a></p>
]]></content>
<summary type="html">
<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><blockquote>
<p>C#的Interface讲的地方也不少,可以参考MSDN中<a href="https://msdn.micros
</summary>
<category term="c#" scheme="http://flyingtime.github.io/tags/c/"/>
</entry>
<entry>
<title>[翻译]MySql Connector NET for .NET Core 1.0</title>
<link href="http://flyingtime.github.io/2016/10/27/%E7%BF%BB%E8%AF%91-MySql-Connector-NET-for-NET-Core-1-0/"/>
<id>http://flyingtime.github.io/2016/10/27/翻译-MySql-Connector-NET-for-NET-Core-1-0/</id>
<published>2016-10-27T14:51:24.000Z</published>
<updated>2016-10-31T02:07:54.000Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote>
<p>.Net Core发展迅猛,最近Entity Framework Core支持Mysql数据库了,现在可以在windows、osx、linux上使用.netcore连接mysql数据库了,英文原文地址:<a href="http://insidemysql.com/mysql-connector-net-for-net-core-1-0/" target="_blank" rel="external">MySql Connector NET for .NET Core 1.0</a></p>
</blockquote>
<h2 id="翻译"><a href="#翻译" class="headerlink" title="翻译"></a>翻译</h2><ul>
<li><strong>.NET Core 和 MySQL Connector NET</strong><br> 这是激动人心的时刻!最近微软发布了.NET Core 1.0,它是一个跨平台实现.NET Framework的实现。.NET Core运行在Windows,Mac OS和Linux上并且是完全开源的!<br> 我们希望使用MySQL Connector NET的用户能够使用.NET Core,所以在过去几个月中我们努力工作,使我们的程序能够完全兼容.NET Core。由于.NET Core并没有完全取代传统的.NET Framework,我们将继续确保我们的程序与这两个框架兼容。<br> 随着这些令人兴奋的变化,我们将继续支持Entity Framwork 7.0和Entity Framework 1.0,包括最新的发布版。<br> 在本文中,我将解释如何安装和设置.NET Core以及如何创建一个简单的示例,连接Mysql数据库取回数据并显示到屏幕上。</li>
<li><strong>Setup</strong><br> .Net Core这个新框架的进一步信息,API,etc等,可以在这个网站中找到:<a href="https://www.microsoft.com/net/core" target="_blank" rel="external">https://www.microsoft.com/net/core</a>。</li>
<li><strong>工具</strong><br> SDK和DOTNET CLI适用于所有支持的平台(见网站就知道支持特定平台的列表)。Visual Studio Code(可在<a href="https://code.visualstudio.com/" target="_blank" rel="external">https://code.visualstudio.com/</a>)是一个新的,完全开源的编辑器,可运行在Windows,Mac和Linux,提供了一个很好的GUI环境进行编辑,编译,甚至调试项目。当安装Visual Studio代码,请确保安装了C#插件,这将允许编译和调试C#项目。</li>
<li><strong>在Windows上安装</strong><br> 安装指南请参考这个网址 <a href="https://www.microsoft.com/net/core#windows" target="_blank" rel="external">https://www.microsoft.com/net/core#windows</a>。<br> 你可以只安装.NET Core 1.0 SDK并且使用Visual Studio Code进行编辑、编译、调试。.NET Core 1.0 SDK的下地址为<a href="https://go.microsoft.com/fwlink/?LinkID=809122." target="_blank" rel="external">https://go.microsoft.com/fwlink/?LinkID=809122</a>。<br> 当然你也可以在Windows系统上选择Visual Studio 2015。如果你不想购买Visual Studio 2015, 你可以使用Visual Studio 2015 Community Edition版本,可以在这里找到<a href="https://go.microsoft.com/fwlink/?LinkId=691978" target="_blank" rel="external">https://go.microsoft.com/fwlink/?LinkId=691978</a>。<br> 要使用.NET Core项目,你必须确保你使用的是Visual Studio 2015 Update3。可以在这里找到<a href="https://go.microsoft.com/fwlink/?LinkId=691129" target="_blank" rel="external">https://go.microsoft.com/fwlink/?LinkId=691129</a>。此外,还有一个单独的下载提供一些在Visual Studio 2015使用的“工具”,可以在这里找到<a href="https://go.microsoft.com/fwlink/?LinkID=824849" target="_blank" rel="external">https://go.microsoft.com/fwlink/?LinkID=824849</a>。</li>
<li><strong>在Linux上安装</strong><br> .NET Core 1.0是兼容多版本Linux变种的。我将解释如何在Ubuntu (14.04或16.04,15.04不支持)或者Linux Mint 17上安装.NET Core 1.0。所使用的指南在这里<a href="https://www.microsoft.com/net/core#ubuntu" target="_blank" rel="external">https://www.microsoft.com/net/core#ubuntu</a>。<br> 同时也支持其他的Liunx发行版, 遵循从指导<a href="https://www.microsoft.com/net/core" target="_blank" rel="external">.NET Core website</a>。<ul>
<li>添加dotnet的apt-get源<br> 首先我们要添加apt-get的源。</li>
<li>Ubuntu 14.04/Linux Mint 17<pre><code class="shell">sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list'
sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
sudo apt-get update
</code></pre>
</li>
<li>Ubuntu 16.04<pre><code class="shell">sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
sudo apt-get update
</code></pre>
</li>
<li>.NET Core SDK<br> 如果你以前安装过.NET Core的任何版本需要运行<a href="https://github.com/dotnet/cli/blob/rel/1.0.0/scripts/obtain/uninstall/dotnet-uninstall-debian-packages.sh" target="_blank" rel="external">该脚本</a>以删除旧版本。在继续安装之前务必删除旧的版本。<br> 使用apt-get安装.NET Core<pre><code class="shell">sudo apt-get install dotnet-dev-1.0.0-preview2-003121
</code></pre>
</li>
</ul>
</li>
<li><strong>在Mac OS上安装</strong><br> 使用指南在这里<a href="https://www.microsoft.com/net/core#macos" target="_blank" rel="external">https://www.microsoft.com/net/core#macos</a><br> 必须要安装最新版本的OpenSSL,最简单的方式是使用Homebrew安装。请使用下面的指南安装Homebrew<a href="http://brew.sh/" target="_blank" rel="external">here</a><br> 安装完Homebrew,请使用下面的命令<pre><code class="shell">brew update
brew install openssl
brew link --force openssl
</code></pre>
<ul>
<li>.NET Core SDK (Mac OS)<br> 请在这里下载安装文件<a href="https://go.microsoft.com/fwlink/?LinkID=809124" target="_blank" rel="external">https://go.microsoft.com/fwlink/?LinkID=809124</a></li>
</ul>
</li>
<li><p><strong>例子</strong><br> 现在我们的SDK已经安装完毕,我们可以继续创建一个示例项目。你可以使用Visual Studio 2015 或 Visual Studio Code。<br> .NET Core有两种不同项目:Library和Console程序。到目前为止.NET Core还不支持GUI样式的程序。这个例子我们将会建立一个console程序。<br> 如果你使用Visual Studio 2015,创建一个“Console Application (.NET Core)”的新项目, 出入工程名并点击“OK”按钮。<br> <img src="/res/Select-Kind-of-project.png" alt=""><br> 如果你是使用dotnet CL和VS Code创建项目,打开命令提示行,为你的项目创建一个新的文件夹, 进入文件夹创建项目</p>
<pre><code class="shell">mkdir MyProject
cd MyProject
dotnet new
</code></pre>
<p> 项目创建完成之后,需要使用“restore”命令下载相关联的程序集<br> 使用Visual Studio 2015在项目上单击右键,在弹出的菜单中选择“Restore Packages”<br> 使用dotnet cli/VS Code</p>
<pre><code class="shell">dotnet restore
</code></pre>
<p> restore完成之后,使用Visual Studio 2015编译项目或使用dotnet cli运行“build”命令</p>
<pre><code class="shell">dotnet build
</code></pre>
<p> 最后,执行这个例子,在Visual Studio 2015上使用F5键或在cli中运行“run”命令</p>
<pre><code class="shell">dotnet run
</code></pre>
<p> 现在你应该看到输出了“Hello World!”<br> 我们现在已经有了一个十分基础的程序。现在让我们添加一些代码和一个.NET Core依赖的MySQL Connector引用。我们将继续使用dotnet cli还有VS Code完成本文的其他部分。<br> 打开在Visual Studio代码的目录。我们将会看到两个文件,Program.cs中和project.json。<br> project.json是我们项目的配置文件,包含项目的一些属性如名字,版本,作者。此外,我们设置构建和打包的选项,建立框架目标还有他们其他的设置如依赖关系。<br> 我们刚才创建的项目有一个“project.json”文件,它看起来是这个样子</p>
<pre><code class="json">{
<span class="attr">"version"</span>: <span class="string">"1.0.0-*"</span>,
<span class="attr">"buildOptions"</span>: {
<span class="attr">"debugType"</span>: <span class="string">"portable"</span>,
<span class="attr">"emitEntryPoint"</span>: <span class="literal">true</span>
},
<span class="attr">"dependencies"</span>: {},
<span class="attr">"frameworks"</span>: {
<span class="attr">"netcoreapp1.0"</span>: {
<span class="attr">"dependencies"</span>: {
<span class="attr">"Microsoft.NETCore.App"</span>: {
<span class="attr">"type"</span>: <span class="string">"platform"</span>,
<span class="attr">"version"</span>: <span class="string">"1.0.0"</span>
}
},
<span class="attr">"imports"</span>: <span class="string">"dnxcore50"</span>
}
}
}
</code></pre>
<p> 为了与Mysql Server建立连接,我们需要添加一个.NET Core版的MySQL Connector引用。我们将在Microsoft.NETCore.App依赖之后添加这个依赖。请注意,我们还需要添加一个不依赖于目标的生成依赖(在“dependencies”分区后面的空白处,”frameworks”分区的前面)。这就是你需要做的。</p>
<pre><code class="json">{
<span class="attr">"version"</span>: <span class="string">"1.0.0-*"</span>,
<span class="attr">"buildOptions"</span>: {
<span class="attr">"debugType"</span>: <span class="string">"portable"</span>,
<span class="attr">"emitEntryPoint"</span>: <span class="literal">true</span>
},
<span class="attr">"dependencies"</span>: {},
<span class="attr">"frameworks"</span>: {
<span class="attr">"netcoreapp1.0"</span>: {
<span class="attr">"dependencies"</span>: {
<span class="attr">"Microsoft.NETCore.App"</span>: {
<span class="attr">"type"</span>: <span class="string">"platform"</span>,
<span class="attr">"version"</span>: <span class="string">"1.0.0"</span>
},
<span class="attr">"MySql.Data.Core"</span>: <span class="string">"7.0.4-IR-191"</span>
},
<span class="attr">"imports"</span>: <span class="string">"dnxcore50"</span>
}
}
}
</code></pre>
<p> 确保我们已经有一个创建MySQL服务器并且在运行,并配置了Sakila样例数据库。如果你需要新建数据库,sql脚本可以在<a href="https://dev.mysql.com/doc/index-other.html" target="_blank" rel="external">这里</a>找到。<br> 当我们改变了依赖关系,我们需要重新restore一下,这样.NET Core会下载NuGet包,这样我们就可以使用它。</p>
<pre><code class="shell">dotnet restore
</code></pre>
<p> 现在打开program.cs源文件,在命名空间部分添加using MySql.Data.MySqlClient并且添加新建和打开连接的代码。</p>
<pre><code class="c#">using System;
using MySql.Data.MySqlClient;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
MySqlConnection connection = new MySqlConnection
{
ConnectionString = "server=<ServerAddress>;user id=<User>;password=<Password>;persistsecurityinfo=True;port=<Port>;database=sakila"
};
connection.Open();
}
}
}
</code></pre>
<p> 现在让我们添加从“Sakila”数据库或者“Category”表信息的相关代码</p>
<pre><code class="c#">using System;
using MySql.Data.MySqlClient;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
MySqlConnection connection = new MySqlConnection
{
ConnectionString = "server=localhost;user id=root;password=;persistsecurityinfo=True;port=3305;database=sakila"
};
connection.Open();
MySqlCommand command = new MySqlCommand("SELECT * FROM sakila.category;", connection);
using (MySqlDataReader reader = command.ExecuteReader())
{
System.Console.WriteLine("Category Id\t\tName\t\tLast Update");
while (reader.Read())
{
string row = $"{reader["category_id"]}\t\t{reader["name"]}\t\t{reader["last_update"]}";
System.Console.WriteLine(row);
}
}
connection.Close();
System.Console.ReadKey();
}
}
}
</code></pre>
<p> 这就是我们需要从服务器获取数据的简单例子的全部内容。让我们构建并运行这个例子(如果你还没有执行restore操作,那么首先需要restore)</p>
<pre><code class="shell">dotnet restore
dotnet build
dotnet run
</code></pre>
<p> 输出的内容如下:</p>
</li>
</ul>
<table>
<thead>
<tr>
<th>Category Id</th>
<th>Name</th>
<th>Last Update</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Action</td>
<td>15/02/2006 04:46:27</td>
</tr>
<tr>
<td>2</td>
<td>Animation</td>
<td>15/02/2006 04:46:27</td>
</tr>
<tr>
<td>3</td>
<td>Children</td>
<td>15/02/2006 04:46:27</td>
</tr>
<tr>
<td>4</td>
<td>Classics</td>
<td>15/02/2006 04:46:27</td>
</tr>
<tr>
<td>5</td>
<td>Comedy</td>
<td>15/02/2006 04:46:27</td>
</tr>
<tr>
<td>6</td>
<td>Documentary</td>
<td>15/02/2006 04:46:27</td>
</tr>
<tr>
<td>7</td>
<td>Drama</td>
<td>15/02/2006 04:46:27</td>
</tr>
<tr>
<td>8</td>
<td>Family</td>
<td>15/02/2006 04:46:27</td>
</tr>
<tr>
<td>9</td>
<td>Foreign</td>
<td>15/02/2006 04:46:27</td>
</tr>
</tbody>
</table>
<p>希望这简单的示例可以帮助你。虽然这篇文章是在Windows上的,但是命令行步骤和代码在Linux和Mac也是一样的。</p>
<h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>谢谢大家观看!有任何疑问或建议请发送邮件联系我:<a href="mailto:flyingtimeice@163.com">flyingtimeice@163.com</a>。</p>
]]></content>
<summary type="html">
<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote>
<p>.Net Core发展迅猛,最近Entity Framework Core支持Mysql数据库了,现在可以在win
</summary>
<category term="c#" scheme="http://flyingtime.github.io/tags/c/"/>
<category term=".netcore" scheme="http://flyingtime.github.io/tags/netcore/"/>
<category term="mysql" scheme="http://flyingtime.github.io/tags/mysql/"/>
</entry>
<entry>
<title>.Netcore Native测试</title>
<link href="http://flyingtime.github.io/2016/10/27/Netcore-Native%E6%B5%8B%E8%AF%95/"/>
<id>http://flyingtime.github.io/2016/10/27/Netcore-Native测试/</id>
<published>2016-10-27T05:45:19.000Z</published>
<updated>2016-10-31T00:48:00.000Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote>
<p>.Netcore的两种部署模式:Framework-dependent deployments (FDD);Self-contained deployments (SCD);FDD感觉跟原来的托管程序是类似的,必须运行在.netcore的环境中,而SCD则是一个打包了所需运行环境的模式。比较感兴趣的是SCD模式,但是发现一个普通的hello world加上运行环境有45M大小。。。这两种模式都是在托管代码下运行的,那么有没有一种原生的编译方式呢?今天我们就折腾一下.netcore的native编译模式。</p>
</blockquote>
<h2 id="具体步骤"><a href="#具体步骤" class="headerlink" title="具体步骤"></a>具体步骤</h2><ol>
<li>本机系统环境<br><img src="/res/my_system.png" alt=""></li>
<li>安装所需环境<ol>
<li>安装openssl<pre><code class="shell">brew upate
brew install openssl
brew link --force openssl
</code></pre>
</li>
<li>安装cmake,下载最新版本的就可以 </li>
</ol>
</li>
<li>构建ILCompiler<pre><code class="shell">git clone https://github.com/dotnet/corert
cd corert/
./build.sh clean Release
</code></pre>
</li>
<li>下载.NET Core SDK<ol>
<li>打开 <a href="https://github.com/dotnet/cli/" target="_blank" rel="external">https://github.com/dotnet/cli/</a></li>
<li>找到 <img src="/res/cli_list.png" alt="">,注意下载标红的那栏</li>
<li>安装下载的.NET Core SDK工具</li>
</ol>
</li>
<li>创建新的测试程序<pre><code class="shell">dotnet new -t console
</code></pre>
</li>
<li>在工程文件夹添加 NuGet.Config,文件内容如下:<pre><code class="xml"> <?xml version="1.0" encoding="utf-8"?>
<span class="tag"><<span class="name">configuration</span>></span>
<span class="tag"><<span class="name">packageSources</span>></span>
<span class="comment"><!--To inherit the global NuGet package sources remove the <clear/> line below --></span>
<span class="tag"><<span class="name">clear</span> /></span>
<span class="tag"><<span class="name">add</span> <span class="attr">key</span>=<span class="string">"dotnet-core"</span> <span class="attr">value</span>=<span class="string">"https://dotnet.myget.org/F/dotnet-core/api/v3/index.json"</span> /></span>
<span class="tag"><<span class="name">add</span> <span class="attr">key</span>=<span class="string">"cli-deps"</span> <span class="attr">value</span>=<span class="string">"https://dotnet.myget.org/F/cli-deps/api/v3/index.json"</span> /></span>
<span class="tag"><<span class="name">add</span> <span class="attr">key</span>=<span class="string">"xunit"</span> <span class="attr">value</span>=<span class="string">"https://www.myget.org/F/xunit/api/v3/index.json"</span> /></span>
<span class="tag"><<span class="name">add</span> <span class="attr">key</span>=<span class="string">"api.nuget.org"</span> <span class="attr">value</span>=<span class="string">"https://api.nuget.org/v3/index.json"</span> /></span>
<span class="tag"></<span class="name">packageSources</span>></span>
<span class="tag"></<span class="name">configuration</span>></span>
</code></pre>
</li>
<li>添加环境变量<br> 在~/.bash_profile添加如下内容(请查看自己corert的项目地址):<pre><code class="shell">export IlcPath="/Users/mac/Documents/corert/bin/Product/OSX.x64.Release/packaging/publish1"
</code></pre>
</li>
<li>执行restore<pre><code class="shell">dotnet restore3
</code></pre>
</li>
<li>在*.csproj最后添加<pre><code class="xml"><span class="tag"><<span class="name">Import</span> <span class="attr">Project</span>=<span class="string">"$(IlcPath)\Microsoft.NETCore.Native.targets"</span> /></span>
</code></pre>
</li>
<li>构建Natvie的测试程序<ol>
<li>使用RyuJIT<pre><code class="shell">dotnet build3 /t:LinkNative /p:IlcPath=<repo_root>\bin\Product\OSX.x64.Release\packaging\publish1
</code></pre>
构建成功:<br> <img src="/res/netnative.png" alt=""></li>
<li>使用CPP代码生成器<pre><code class="shell">dotnet build3 /t:LinkNative /p:IlcPath=<repo_root>\bin\Product\OSX.x64.Release\packaging\publish1 /p:NativeCodeGen=cpp
</code></pre>
<blockquote>
<p><strong>注意</strong> 在Mac系统下最后的/p:Additional Compiler Flags=/MTd是需要去掉的</p>
</blockquote>
</li>
<li>第一种方式生成的程序为5.3M,而第二种构建的方式生成的程序为3.2M。</li>
</ol>
</li>
</ol>
<h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>.Net Core是一个很有前途的项目,M$再次用强大的实力让我折服,以后可以用C#写原生的代码了,native编译不再是梦想,C#的开发效率,C++的运行效率,开发周期跟运行时间的完美平衡,祝愿.Net Core项目更加强大,谢谢观看!</p>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://docs.microsoft.com/en-us/dotnet/articles/core/deploying/" target="_blank" rel="external">.Netcore 程序部署</a><br><a href="https://blogs.msdn.microsoft.com/msdntaiwan/2016/09/20/selfcontainednetcoreapplications/" target="_blank" rel="external">獨立的 .NET Core 應用程式</a><br><a href="https://github.com/dotnet/corert/blob/master/Documentation/prerequisites-for-building.md" target="_blank" rel="external">构建ILCompiler所需环境</a><br><a href="https://github.com/dotnet/corert/blob/master/Documentation/how-to-build-and-run-ilcompiler-in-console-shell-prompt.md" target="_blank" rel="external">构建ILCompiler程序</a></p>
]]></content>
<summary type="html">
<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote>
<p>.Netcore的两种部署模式:Framework-dependent deployments (FDD);Sel
</summary>
<category term="c#" scheme="http://flyingtime.github.io/categories/c/"/>
<category term="c#" scheme="http://flyingtime.github.io/tags/c/"/>
<category term=".netcore" scheme="http://flyingtime.github.io/tags/netcore/"/>
<category term="native" scheme="http://flyingtime.github.io/tags/native/"/>
</entry>
<entry>
<title>Golang搭建单、双向自认证HTTPS服务器</title>
<link href="http://flyingtime.github.io/2016/10/26/Golang%E6%90%AD%E5%BB%BA%E5%8D%95%E3%80%81%E5%8F%8C%E5%90%91%E8%87%AA%E8%AE%A4%E8%AF%81HTTPS%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
<id>http://flyingtime.github.io/2016/10/26/Golang搭建单、双向自认证HTTPS服务器/</id>
<published>2016-10-26T01:25:51.000Z</published>
<updated>2016-11-03T07:40:04.000Z</updated>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><blockquote>
<p>2015年双11期间淘宝、天猫实现了全站式https安全传输,web安全问题已经成了人们关注的话题,那什么是https呢?如何实现单、双向自认证https服务器呢?接下来我们将一一介绍。</p>
</blockquote>
<h2 id="一、HTTPS相关概念已经认证流程"><a href="#一、HTTPS相关概念已经认证流程" class="headerlink" title="一、HTTPS相关概念已经认证流程"></a>一、HTTPS相关概念已经认证流程</h2><h4 id="基本概念:"><a href="#基本概念:" class="headerlink" title="基本概念:"></a>基本概念:</h4><p><a href="http://baike.baidu.com/link?url=XuEFqp8HTAIWBO12QMzj54K1iIBGPL6VJGPEn85nyCirdG8LE104hMYvOeDgfucyMf3gu1zPLap3i0BKb-SKHa" target="_blank" rel="external"><strong>HTTPS</strong></a>(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。这个系统的最初研发由网景公司(Netscape)进行,并内置于其浏览器Netscape Navigator中,提供了身份验证与加密通讯方法。现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。关于https详细介绍请见:<a href="http://studygolang.com/articles/2984" target="_blank" rel="external">大型网站的HTTPS实践</a>。</p>
<p><strong>SSL</strong>(Secure Socket Layer):是Netscape公司设计的主要用于WEB的安全传输协议。从名字就可以看出它在https协议栈中负责实现上面提到的加密层。</p>
<p><strong>数字证书</strong>:一种文件的名称,好比一个机构或人的签名,能够证明这个机构或人的真实性。其中包含的信息,用于实现上述功能。</p>
<p><strong>加密和认证</strong>:加密是指通信双方为了防止铭感信息在信道上被第三方窃听而泄漏,将明文通过加密变成密文,如果第三方无法解密的话,就算他获得密文也无能为力;认证是指通信双方为了确认对方是值得信任的消息发送或接受方,而不是使用假身份的非法者,采取的确认身份的方式。只有同时进行了加密和认证才能保证通信的安全,因此在SSL通信协议中这两者都被应。早期一般是用对称加密算法,现在一般都是不对称加密,最常见的算法就是RSA。</p>
<p><strong>消息摘要</strong>:这个技术主要是为了避免消息被篡改。消息摘要是把一段信息,通过某种算法,得出一串字符串。这个字符串就是消息的摘要。如果消息被篡改(发生了变化),那么摘要也一定会发生变化(如果2个不同的消息生成的摘要是一样的,那么这就叫发生了碰撞)。消息摘要的算法主要有MD5和SHA,在证书领域,一般都是用SHA(安全哈希算法)。</p>
<p>数字证书、加密和认证、消息摘要三个技术结合起来,就是在HTTPS中广泛应用的证书(certificate),证书本身携带了加密/解密的信息,并且可以标识自己的身份,也自带消息摘要。</p>
<h4 id="HTTPS认证过程:"><a href="#HTTPS认证过程:" class="headerlink" title="HTTPS认证过程:"></a>HTTPS认证过程:</h4><pre><code>1. 浏览器发送一个连接请求给安全服务器。
2. 服务器将自己的证书,以及同证书相关的信息发送给客户浏览器。
3. 客户浏览器检查服务器送过来的证书是否是由自己信赖的 CA 中心所签发的。如果是,就继续执行协议;如果不是,客户浏览器就给客户一个警告消息:警告客户这个证书不是可以信赖的,询问客户是否需要继续。
4. 接着客户浏览器比较证书里的消息,例如域名和公钥,与服务器刚刚发送的相关消息是否一致,如果是一致的,客户浏览器认可这个服务器的合法身份。
5. 服务器要求客户发送客户自己的证书。收到后,服务器验证客户的证书,如果没有通过验证,拒绝连接;如果通过验证,服务器获得用户的公钥。
6. 客户浏览器告诉服务器自己所能够支持的通讯对称密码方案。
7. 服务器从客户发送过来的密码方案中,选择一种加密程度最高的密码方案,用客户的公钥加过密后通知浏览器。
8. 浏览器针对这个密码方案,选择一个通话密钥,接着用服务器的公钥加过密后发送给服务器。
9. 服务器接收到浏览器送过来的消息,用自己的私钥解密,获得通话密钥。
10. 服务器、浏览器接下来的通讯都是用对称密码方案,对称密钥是加过密的。
</code></pre><p>上面所述的是双向认证 SSL 协议的具体通讯过程,这种情况要求服务器和用户双方都有证书。单向认证 SSL 协议不需要客户拥有 CA 证书,具体的过程相对于上面的步骤,只需将服务器端验证客户证书的过程去掉,以及在协商对称密码方案,对称通话密钥时,服务器发送给客户的是没有加过密的 (这并不影响 SSL 过程的安全性)密码方案。这样,双方具体的通讯内容,就是加过密的数据,如果有第三方攻击,获得的只是加密的数据,第三方要获得有用的信息,就需要对加密 的数据进行解密,这时候的安全就依赖于密码方案的安全。而幸运的是,目前所用的密码方案,只要通讯密钥长度足够的长,就足够的安全。这也是我们强调要求使用128 位加密通讯的原因。</p>
<h2 id="二、自认证根证书"><a href="#二、自认证根证书" class="headerlink" title="二、自认证根证书"></a>二、自认证根证书</h2><ol>
<li><p>创建根证书密钥文件(自己做CA)root.key:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl genrsa -des3 -out root.key 2048</div></pre></td></tr></table></figure>
<p> 需要输入两次私钥密码<br> <img src="/res/1.png" alt=""></p>
</li>
<li><p>创建根证书的申请文件root.csr:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl req -new -key root.key -out root.csr</div></pre></td></tr></table></figure>
<p> 输入root.key的密码<br> <img src="/res/2.png" alt=""></p>
</li>
<li><p>创建根证书root.crt:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl x509 -req -days 3650 -sha256 -extensions v3_ca -signkey root.key -in root.csr -out root.crt</div></pre></td></tr></table></figure>
<p> 生成根证书<br> <img src="/res/3.png" alt=""></p>
</li>
</ol>
<h2 id="三、SSL单向认证"><a href="#三、SSL单向认证" class="headerlink" title="三、SSL单向认证"></a>三、SSL单向认证</h2><ol>
<li><p>创建服务器证书秘钥</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl genrsa –des3 -out server.key 2048</div></pre></td></tr></table></figure>
<p> 需要输入两次私钥密码<br> <img src="/res/4.png" alt=""></p>
</li>
<li><p>去除key口令</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl rsa -in server.key -out server.key</div></pre></td></tr></table></figure>
<p> 需要输入私钥密码<br> <img src="/res/5.png" alt=""></p>
</li>
<li><p>创建服务器证书申请文件server.csr</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl req -new -key server.key -out server.csr</div></pre></td></tr></table></figure>
<p> “Common Name”最好跟网站的域名一致<br> <img src="/res/6.png" alt=""></p>
</li>
<li><p>创建服务器证书server.crt</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl x509 -req -days 365 -sha256 -extensions v3_req -CA root.crt -CAkey root.key -CAcreateserial -in server.csr -out server.crt</div></pre></td></tr></table></figure>
<p> 需要输入根私钥密码<br> <img src="/res/7.png" alt=""> </p>
</li>
<li><p>客户端导入根证书并添加到“信任的根服务站点”<br> <img src="/res/8.png" alt=""><br> <img src="/res/9.png" alt=""><br> <img src="/res/10.png" alt=""><br> <img src="/res/11.png" alt=""><br> <img src="/res/12.png" alt=""><br> <img src="/res/13.png" alt=""><br> <img src="/res/14.png" alt=""><br> <img src="/res/15.png" alt=""> </p>
</li>
<li><p>golang实现简单的https服务器</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> main</div><div class="line"></div><div class="line"><span class="keyword">import</span> (</div><div class="line"> <span class="string">"io"</span></div><div class="line"> <span class="string">"log"</span></div><div class="line"> <span class="string">"net/http"</span></div><div class="line">)</div><div class="line"> </div><div class="line"><span class="function"><span class="keyword">func</span> <span class="title">handler</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> {</div><div class="line"> io.WriteString(w, <span class="string">"golang https server"</span>)</div><div class="line">}</div><div class="line"> </div><div class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</div><div class="line"> http.HandleFunc(<span class="string">"/"</span>, handler)</div><div class="line"> <span class="keyword">if</span> err := http.ListenAndServeTLS(<span class="string">":8080"</span>, <span class="string">"server.crt"</span>, <span class="string">"server.key"</span>, <span class="literal">nil</span>); err != <span class="literal">nil</span> {</div><div class="line"> log.Fatal(<span class="string">"ListenAndServe:"</span>, err)</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p> 在浏览器中测试<br> <img src="/res/16.png" alt=""></p>
</li>
</ol>
<h2 id="四、SSL双向认证"><a href="#四、SSL双向认证" class="headerlink" title="四、SSL双向认证"></a>四、SSL双向认证</h2><p>在单向认证的基础上添加客户端证书并在golang服务器源码上添加客户端认证相关代码</p>
<ol>
<li><p>创建客户端证书私钥</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl genrsa -des3 -out client.key 2048</div></pre></td></tr></table></figure>
<p> 需要输入两次私钥密码<br> <img src="/res/17.png" alt=""></p>
</li>
<li><p>去除key口令</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl rsa -in client.key -out client.key</div></pre></td></tr></table></figure>
<p> 需要输入私钥密码<br> <img src="/res/18.png" alt=""></p>
</li>
<li><p>创建客户端证书申请文件client.csr</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl req -new -key client.key -out client.csr</div></pre></td></tr></table></figure>
<p> <img src="/res/19.png" alt=""> </p>
</li>
<li><p>创建客户端证书文件client.crt</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl x509 -req -days 365 -sha256 -extensions v3_req -CA root.crt -CAkey root.key -CAcreateserial -in client.csr -out client.crt</div></pre></td></tr></table></figure>
<p> <img src="/res/20.png" alt=""></p>
</li>
<li><p>将客户端证书文件client.crt和客户端证书密钥文件client.key合并成客户端证书安装包client.pfx</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$openssl pkcs12 -export -in client.crt -inkey client.key -out client.pfx</div></pre></td></tr></table></figure>
<p> 设置客户端安装时的密码<br> <img src="/res/23.png" alt=""></p>
</li>
<li><p>添加客户端证书<br> 参见服务器端添加证书,客户端证书添加到“个人”里面就可以<br> <img src="/res/21.png" alt=""></p>
</li>
<li><p>修改服务器代码</p>
<pre><code class="Go"><span class="keyword">package</span> main
<span class="keyword">import</span> (
<span class="string">"crypto/tls"</span>
<span class="string">"crypto/x509"</span>
<span class="string">"io"</span>
<span class="string">"io/ioutil"</span>
<span class="string">"log"</span>
<span class="string">"net/http"</span>
)
<span class="keyword">type</span> httpsHandler <span class="keyword">struct</span> {
}
<span class="function"><span class="keyword">func</span> <span class="params">(*httpsHandler)</span> <span class="title">ServeHTTP</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> {
io.WriteString(w, <span class="string">"golang https server!!!"</span>)
}
<span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {
pool := x509.NewCertPool()
caCertPath := <span class="string">"root.crt"</span>
caCrt, err := ioutil.ReadFile(caCertPath)
<span class="keyword">if</span> err != <span class="literal">nil</span> {
log.Fatal(<span class="string">"ReadFile err:"</span>, err)
<span class="keyword">return</span>
}
pool.AppendCertsFromPEM(caCrt)
s := &http.Server{
Addr: <span class="string">":8080"</span>,
Handler: &httpsHandler{},
TLSConfig: &tls.Config{
ClientCAs: pool,
ClientAuth: tls.RequireAndVerifyClientCert,
},
}
<span class="keyword">if</span> err = s.ListenAndServeTLS(<span class="string">"server.crt"</span>, <span class="string">"server.key"</span>); err != <span class="literal">nil</span> {
log.Fatal(<span class="string">"ListenAndServeTLS err:"</span>, err)
}
}
</code></pre>
</li>
<li><p>使用golang访问https服务器</p>
<pre><code class="Go"><span class="keyword">package</span> main
<span class="keyword">import</span> (
<span class="string">"crypto/tls"</span>
<span class="string">"crypto/x509"</span>
<span class="string">"io/ioutil"</span>
<span class="string">"log"</span>
<span class="string">"net/http"</span>
)
<span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {
pool := x509.NewCertPool()
caCertPath := <span class="string">"root.crt"</span>
caCrt, err := ioutil.ReadFile(caCertPath)
<span class="keyword">if</span> err != <span class="literal">nil</span> {
log.Fatal(<span class="string">"ReadFile err:"</span>, err)
<span class="keyword">return</span>
}
pool.AppendCertsFromPEM(caCrt)
cliCrt, err := tls.LoadX509KeyPair(<span class="string">"client.crt"</span>, <span class="string">"client.key"</span>)
<span class="keyword">if</span> err != <span class="literal">nil</span> {
log.Fatal(<span class="string">"LoadX509KeyPair err:"</span>, err)
<span class="keyword">return</span>
}
tr := &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: pool,
Certificates: []tls.Certificate{cliCrt},
},
}
client := &http.Client{Transport: tr}
resp, err := client.Get(<span class="string">"https://localhost:8080"</span>)
<span class="keyword">if</span> err != <span class="literal">nil</span> {
log.Fatal(<span class="string">"client error:"</span>, err)
<span class="keyword">return</span>
}
<span class="keyword">defer</span> resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
log.Println(<span class="keyword">string</span>(body))
}
</code></pre>
<p>在浏览器中测试<br> <img src="/res/22.png" alt=""></p>
</li>
</ol>
<h3 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h3><p>希望通过这次实例能让大家更好的理解、应用https,谢谢观看。<br>相关代码:<a href="https://github.com/flyingtime/go-https" target="_blank" rel="external">go-https</a></p>
]]></content>
<summary type="html">
<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><blockquote>
<p>2015年双11期间淘宝、天猫实现了全站式https安全传输,web安全问题已经成了人们关注的话题,那什么是htt
</summary>
<category term="golang" scheme="http://flyingtime.github.io/categories/golang/"/>
<category term="golang" scheme="http://flyingtime.github.io/tags/golang/"/>
<category term="https" scheme="http://flyingtime.github.io/tags/https/"/>
</entry>
<entry>
<title>VS2015 Entity Framework 6.x Mysql的一些问题</title>
<link href="http://flyingtime.github.io/2016/06/29/VS2015-Entity-Framework-6-x-Mysql%E7%9A%84%E4%B8%80%E4%BA%9B%E9%97%AE%E9%A2%98/"/>
<id>http://flyingtime.github.io/2016/06/29/VS2015-Entity-Framework-6-x-Mysql的一些问题/</id>
<published>2016-06-29T10:50:36.000Z</published>
<updated>2016-10-27T14:53:17.000Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote>
<p>在VS 2015中使用Entity Framework 6.x时,连接Mysql数据库常会出现一些问题,在这里记录了一些自己在项目中遇到的问题,希望大家可以参考一下,在以后的项目中避免在类似的问题中花费过多的时间</p>
</blockquote>
<h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><ul>
<li>如果自己在系统中安装了mysql connector,并且自己在项目中使用Nuget安装了新的Entity FrameWork for Mysql,当Mysql.Data.Core的版本跟mysql connector中的版本不一致的话会出现一些莫名其妙的问题。可以在直接删除mysql connector工具或者在项目引用中添加mysql connector的中Mysql.Data.dll、Mysql.Web.dll、Mysql.Data.Entity.EF6.dll</li>
<li>修改web.config或者app.config<br>删除:<pre><code class="xml"><span class="tag"><<span class="name">entityFramework</span>></span>
<span class="tag"><<span class="name">defaultConnectionFactory</span> <span class="attr">type</span>=<span class="string">"System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"</span>></span>
<span class="tag"><<span class="name">parameters</span>></span>
<span class="tag"><<span class="name">parameter</span> <span class="attr">value</span>=<span class="string">"v11.0"</span> /></span>
<span class="tag"></<span class="name">parameters</span>></span>
<span class="tag"></<span class="name">defaultConnectionFactory</span>></span>
<span class="tag"><<span class="name">providers</span>></span>
<span class="tag"><<span class="name">provider</span> <span class="attr">invariantName</span>=<span class="string">"System.Data.SqlClient"</span> <span class="attr">type</span>=<span class="string">"System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"</span> /></span>
<span class="tag"></<span class="name">providers</span>></span>
<span class="tag"></<span class="name">entityFramework</span>></span>
</code></pre>
添加:<pre><code class="xml"><span class="tag"><<span class="name">entityFramework</span>></span>
<span class="tag"><<span class="name">defaultConnectionFactory</span> <span class="attr">type</span>=<span class="string">"MySql.Data.Entity.MySqlConnectionFactory, MySql.Data.Entity.EF6"</span> /></span>
<span class="tag"><<span class="name">providers</span>></span>
<span class="tag"><<span class="name">provider</span> <span class="attr">invariantName</span>=<span class="string">"MySql.Data.MySqlClient"</span> <span class="attr">type</span>=<span class="string">"MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6"</span> /></span>
<span class="tag"></<span class="name">providers</span>></span>
<span class="tag"></<span class="name">entityFramework</span>></span>
</code></pre>
</li>
<li><p>连接Mysql出现的一个错误:<br><img src="/res/mysql_error.png" alt=""><br>这其实是个bug,mysql的bug… …解决方法很简单,要把mysql的一个优化项给关了.<br>详见:<a href="http://stackoverflow.com/questions/33575109/mysql-entity-the-value-for-column-isprimarykey-in-table-tabledetails-is" target="_blank" rel="external">http://stackoverflow.com/questions/33575109/mysql-entity-the-value-for-column-isprimarykey-in-table-tabledetails-is</a></p>
<blockquote>
<p>Open Services (services.msc) and restart MySQL57 service.<br>Execute the following commands in MySQL. use database_name;<br>Set global optimizer_switch=’derived_merge=off’;<br>Set optimizer_switch=’derived_merge=off’.</p>
</blockquote>
</li>
<li><p>在Add-Migration 的时候出现“未为提供程序“MySql.Data.MySqlClient”找到任何 MigrationSqlGenerator。请在目标迁移配置类中使用 SetSqlGenerator 方法以注册其他 SQL 生成器”,解决办法:在DbContext类上面添加特性:</p>
<pre><code class="c#">[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]
public class XXDbContext : DbContext
{
}
</code></pre>
</li>
<li>当在XXDbContext中添加特性:[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))],在创建新的controller时,会出现如下错误:<br><img src="/res/mysql_migration_error.png" alt=""><br>解决办法:<ol>
<li>在创建controller时注释掉[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]</li>
<li>在Add-Migration时取消注释[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]</li>
</ol>