JNI_OnLoad:
调用System.loadLibrary()函数时, 内部就会去查找so中的 JNI_OnLoad 函数,如果存在此函数则调用。
JNI_OnLoad会:
告诉 VM 此 native 组件使用的 JNI 版本。
对应了Java版本,android中只支持JNI_VERSION_1_2 、JNI_VERSION_1_4、JNI_VERSION_1_6,其中JNI_VERSION_1_1这个不能用,用它会报错的。
在JDK1.8有 JNI_VERSION_1_8。
下面咱们来写一个该函数:
编译运行:
那要这说这个函数有啥用呢?大有用处,咱们先来看一下该函数的第一个参数:
动态注册就其中的一个用处,所以接下来看一下学习一下动态注册。
动态注册:
在此之前我们一直在jni中使用的 Java_PACKAGENAME_CLASSNAME_METHODNAME 来进行与java方法的匹配,这种方式我们称之为静态注册。如这个:
其native方法就是按照 Java_PACKAGENAME_CLASSNAME_METHODNAME 规则来进行定义的,如下:
而动态注册则意味着方法名可以不用这么长了,也就是我们可以抛开 Java_PACKAGENAME_CLASSNAME_METHODNAME 这个规则动态DIV,在android aosp源码中就大量的使用了动态注册的形式。下面就来实现咱们的动态注册,先在Java层声明一个native方法:
然后咱们在CPP中定义一个函数,不按照 Java_PACKAGENAME_CLASSNAME_METHODNAME ,如下:
接下来则就需要动态注册将这两个进行对应上,首先咱们将JNI_OnLoad这个函数的第一个参数用全局变量保存一下,因为在未来其它函数实现中都有可能用到它,所以:
然后关键的对应代码来了:需要在cpp中定义一个JNINativeMethod数组,里面则会存放各映射关系,如下:
其实它是一个结构体,咱们来看一下它的定义:
所以根据结构体的定义,咱们就来动态注册一下:
动态注册好之后,咱们在cpp的函数中打印一句话用来看输出效果:
接下来来要声明哪一个Java类需要动态注册,需要写全类名,如下:
然后此时就需要利用JNI_OnLoad函数中的JavaVM对其进行动态注册,具体如何搞呢?对于JNI方法实现中最重要的参数则是JNIEnv啦:
,所以首先咱们也得利用它,但是在JNI_OnLoad函数中只有JavaVM参数,木有JNIEnv,怎么弄呢?当然是可以通过JavaVM这个参数获得JNIEnv喽,具体写法如下:
其中r的返回值小于0则是失败,等于0则是成功,接下来则用反射来获取咱们之前声明的className变量的class对象,如下:
接着就开始注册啦,具体做法如下:
下面来运行一下看能否对应上动态注册的函数:
嗯~~确实达到了动态映射,不过咱们再来定义另外一个带参数的native方法会发现一个问题,如下:
然后在cpp中定义对应的实现:
然后再运行看效果:
当有参数的时候这里就得特别的注意啦,在平常咱们静态注册时每个函数都会有这两个参数,如下:
所以是不是在动态注册有带参数的情况下也得要加上这两个参数呢?咱们试试:
一切正常了,所以。。在动态注册时得特别注意带参数的情况~~
native线程调用Java:
native调用java需要使用JNIEnv这个结构体,而JNIEnv是由Jvm传入与线程相关的变量。
但是可以通过JavaVM的AttachCurrentThread方法来获取到当前线程中的JNIEnv指针。
咱们先来声明一个ndk方法:
而要用到线程其实是有两种方式:一是用到posix线程方式,还有一种是用C++ 11的方式,这里用标准的posix线程方式,先引入头文件:
然后创建一个线程:
假如说我们在native层开个线程去下载东东,然后下载完成之后会通知应用Java层,那么肯定就存在Native线程会要去调用Java方法的场景,所以下面就来模拟一下:
咱们在MainActivity中定义一个通知结果的方法,如下:
然后咱们在线程中来反射这个方法,而根据经验咱们需要在线程执行函数中来获取如下两个参数:
而执行函数只能接收一个参数,所以咱们声明一个结构体来对这两个参数进行包装一下,如下:
然后咱们将参数传到threadTask参数中,如下:
然咱们来在执行方法中来反射调用Java中的updateUI方法,由于之前都学过了,直接上代码:
编译运行:
抛异常崩掉了,这是为啥呢,此时的日志报得有些模糊,可以将Logcat的TAG过滤去掉,就可以看到堆栈信息了,如下:
11-09 09:29:01.581 2018-2032/? E/dalvikvm: JNI ERROR: non-VM thread making JNI call (GetObjectClass)
VM aborting
11-09 09:29:01.581 2018-2032/com.jni.test A/libc: Fatal signal 6 (SIGABRT) at 0x000007e2 (code=-6), thread 2032 (com.jni.test)
11-09 09:29:01.605 680-686/? I/jdwp: Ignoring second debugger -- accepting and dropping
11-09 09:29:01.625 877-883/? I/jdwp: Ignoring second debugger -- accepting and dropping
11-09 09:29:01.669 1390-1396/? I/jdwp: Ignoring second debugger -- accepting and dropping
11-09 09:29:01.685 222-222/? I/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'generic/vbox86p/vbox86p:4.4.4/KTU84P/14:userdebug/test-keys'
Revision: '0'
pid: 2018, tid: 2032, name: com.jni.test >>> com.jni.test <<<
11-09 09:29:01.689 222-222/? I/DEBUG: signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
11-09 09:29:01.701 817-823/? I/jdwp: Ignoring second debugger -- accepting and dropping
11-09 09:29:01.713 756-762/? I/jdwp: Ignoring second debugger -- accepting and dropping
11-09 09:29:01.729 572-578/? I/jdwp: Ignoring second debugger -- accepting and dropping
11-09 09:29:01.741 1469-1475/? I/jdwp: Ignoring second debugger -- accepting and dropping
11-09 09:29:01.905 226-559/? W/genymotion_audio: out_write() limiting sleep time 1845522210 to 39909
11-09 09:29:01.957 222-222/? I/DEBUG: eax 00000000 ebx 000007e2 ecx 000007f0 edx 00000006
esi 000007f0 edi 00000000
xcs 00000073 xds 0000007b xes 0000007b xfs 00000000 xss 0000007b
eip b76b2df6 ebp b7717ce0 esp 952c99a0 flags 00200207
backtrace:
#00 pc 0003bdf6 /system/lib/libc.so (tgkill+22)
#01 pc 00000005 <unknown>
stack:
11-09 09:29:01.961 222-222/? I/DEBUG: 952c9960 00000000
952c9964 b7713268 /system/lib/libc.so
952c9968 00000000
952c996c b7684f79 /system/lib/libc.so (pthread_mutex_unlock+25)
952c9970 b771318c /system/lib/libc.so
952c9974 b7921568 [heap]
952c9978 00000015
952c997c 00000000
952c9980 00000000
952c9984 b76d1846 /system/lib/libc.so (funlockfile+6)
952c9988 b7712fcc /system/lib/libc.so
952c998c b76bce96 /system/lib/libc.so (__sflush_locked+150)
952c9990 00000000
952c9994 00000000
952c9998 b7684da9 /system/lib/libc.so (pthread_mutex_lock+9)
952c999c b7712fcc /system/lib/libc.so
#00 952c99a0 00000006
952c99a4 000007f0
952c99a8 b7712fcc /system/lib/libc.so
952c99ac b768f556 /system/lib/libc.so (pthread_kill+102)
952c99b0 000007e2
952c99b4 000007f0
952c99b8 00000006
952c99bc 00000000
952c99c0 b7713268 /system/lib/libc.so
952c99c4 00000000
952c99c8 b768f4f9 /system/lib/libc.so (pthread_kill+9)
952c99cc b7712fcc /system/lib/libc.so
952c99d0 952c9a1c [stack:2032]
952c99d4 952c9c5c [stack:2032]
952c99d8 37900019
952c99dc b768f91c /system/lib/libc.so (raise+44)
不过报得也不是太明显,但是从标红的地方来看肯定是线程那块出问题了,那具体是哪句代码造成呢,可以用debug进行进一步定位跟踪,如下:
往下走:
也就是说问题代码出在:
这是为何呢?从理解上来看貌似代码没啥问题的呀,其原则在于JNIEnv是不能跨线程使用的,也就是说:
此时怎么解决呢?还记得之前我们的JavaVM已经存为全局变量了么,如下:
它就有用武之地啦,具体如何弄呢?
然后此时再编译运行:
发现还是报错。。经过查看更加详细的日志可以发现原因如下:
这是因为这个参数需要用全局共享的办法来在子线程中用,所以修改程序如下:
编译运行:
Linux 文件权限、VIM、防火墙:
关于NDK这块还涉及到Linux的一些基础使用,这个东东其实就是熟能生巧,其实在之前已经对其基本的用法进行了专门的学习,但是为了在将来NDK学习打下更扎实的基础所以这里也整体做一个了解回顾。
SSH连接:
无论是mac还是windows的都可以选择下载自己喜欢的远程登陆客户端工具,通过ssh协议连接到远程主机。
客户端的使用非常方便。但也有喜欢使用命令行的方式来进行连接,所以下面来看一下命令如何连:
使用root登陆1.1.1.1:(默认端口为22)
ssh root@1.1.1.1
也可以使用-p指定 ssh主机配置的端口
ssh -p 222 root@1.1.1.1
环境变量:
和Windows不同,Linux环境变量配置需要使用 export
声明。如:
export PATH=${PATH}:java/bin:android/platform-tools
如果直接在终端中输入命令,则设置PATH环境变量的值,但其作用范围仅限于当前会话。即临时环境变量。
如果说要设置永久的环境变量,涉及但不限于“profile【推荐用它】、bashrc、bash_profile ”这三个文件,其用其它一种就成,
profile:位于这个目灵:/etc/profile,如下:
然后在这个文件里面用export进行环境变量配置,这是对所有用户都生效,也就是如果电脑中有多个用户,全局生效。
bash_profile:它位于~/.bash_profile,如下:
但是跟/etc/prifile不同的时,这个设置只针对当前用户有效,如果切换其它用户则设置的环境变量是不生效的。
bashrc:它位于~/.bashrc,如下:
它也是跟某个用户相关的配置。
对于这三个环境变量相关的配置文件而言:首先读入/etc/profile
,读取当前用户目录内的~/.bash_profile
;最后,根据用户帐号读取~/.bashrc
。
/etc/
是系统全局环境变量设定;~/
是用户私有环境变量设定。
在修改配置文件后,可使用source /etc/profile
刷新。
权限:
Linux系统从诞生就被设计为多用户系统,不同的用户处于不同的地位,拥有不同的权限。为了保护系统安全,Linux系统对不同的用户访问同一文件的权限做了不同而规定。
在Linux中可以通过 `ls -l` 显示文件的属性以及文件所属的用户和组,如下:
其中:
其中具体的信息如下图:
在Linux中第一个字符代表这个文件是目录、文件或者链接等等,如下:
,其涉及到类型的有如下:
然后是三个为一组的rwx
, 其中r
表示可读,w
表示可写, x
表示可执行。对于每个文件来说,它都有一个特定的所有者,也就是对该文件具有所有权的用户。同时在Linux中用户都是按组来进行分类的,一个用户属于一个或多个组。文件所有者之外的用户又分为文件所有者的同组用户和其他用户。可以使用以下命令查看当前使用的用户信息:
如下:
更改文件所属:
这里先介绍命令用法:咱们来试验一下,先新建一个目录:
接下来咱们来修改该文件的所属用户,先查看一下当前系统存在的用户,可以使用如下命令:
xiongweideMacBook-Pro:linux xiongwei$ cat /etc/passwd ## # User Database # # Note that this file is consulted directly only when the system is running # in single-user mode. At other times this information is provided by # Open Directory. # # See the opendirectoryd(8) man page for additional information about # Open Directory. ## nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false root:*:0:0:System Administrator:/var/root:/bin/sh daemon:*:1:1:System Services:/var/root:/usr/bin/false _uucp:*:4:4:Unix to Unix Copy Protocol:/var/spool/uucp:/usr/sbin/uucico _taskgated:*:13:13:Task Gate Daemon:/var/empty:/usr/bin/false _networkd:*:24:24:Network Services:/var/networkd:/usr/bin/false _installassistant:*:25:25:Install Assistant:/var/empty:/usr/bin/false _lp:*:26:26:Printing Services:/var/spool/cups:/usr/bin/false _postfix:*:27:27:Postfix Mail Server:/var/spool/postfix:/usr/bin/false _scsd:*:31:31:Service Configuration Service:/var/empty:/usr/bin/false _ces:*:32:32:Certificate Enrollment Service:/var/empty:/usr/bin/false _appstore:*:33:33:Mac App Store Service:/var/empty:/usr/bin/false _mcxalr:*:54:54:MCX AppLaunch:/var/empty:/usr/bin/false _appleevents:*:55:55:AppleEvents Daemon:/var/empty:/usr/bin/false _geod:*:56:56:Geo Services Daemon:/var/db/geod:/usr/bin/false _serialnumberd:*:58:58:Serial Number Daemon:/var/empty:/usr/bin/false _devdocs:*:59:59:Developer Documentation:/var/empty:/usr/bin/false _sandbox:*:60:60:Seatbelt:/var/empty:/usr/bin/false _mdnsresponder:*:65:65:mDNSResponder:/var/empty:/usr/bin/false _ard:*:67:67:Apple Remote Desktop:/var/empty:/usr/bin/false _www:*:70:70:World Wide Web Server:/Library/WebServer:/usr/bin/false _eppc:*:71:71:Apple Events User:/var/empty:/usr/bin/false _cvs:*:72:72:CVS Server:/var/empty:/usr/bin/false _svn:*:73:73:SVN Server:/var/empty:/usr/bin/false _mysql:*:74:74:MySQL Server:/var/empty:/usr/bin/false _sshd:*:75:75:sshd Privilege separation:/var/empty:/usr/bin/false _qtss:*:76:76:QuickTime Streaming Server:/var/empty:/usr/bin/false _cyrus:*:77:6:Cyrus Administrator:/var/imap:/usr/bin/false _mailman:*:78:78:Mailman List Server:/var/empty:/usr/bin/false _appserver:*:79:79:Application Server:/var/empty:/usr/bin/false _clamav:*:82:82:ClamAV Daemon:/var/virusmails:/usr/bin/false _amavisd:*:83:83:AMaViS Daemon:/var/virusmails:/usr/bin/false _jabber:*:84:84:Jabber XMPP Server:/var/empty:/usr/bin/false _appowner:*:87:87:Application Owner:/var/empty:/usr/bin/false _windowserver:*:88:88:WindowServer:/var/empty:/usr/bin/false _spotlight:*:89:89:Spotlight:/var/empty:/usr/bin/false _tokend:*:91:91:Token Daemon:/var/empty:/usr/bin/false _securityagent:*:92:92:SecurityAgent:/var/db/securityagent:/usr/bin/false _calendar:*:93:93:Calendar:/var/empty:/usr/bin/false _teamsserver:*:94:94:TeamsServer:/var/teamsserver:/usr/bin/false _update_sharing:*:95:-2:Update Sharing:/var/empty:/usr/bin/false _installer:*:96:-2:Installer:/var/empty:/usr/bin/false _atsserver:*:97:97:ATS Server:/var/empty:/usr/bin/false _ftp:*:98:-2:FTP Daemon:/var/empty:/usr/bin/false _unknown:*:99:99:Unknown User:/var/empty:/usr/bin/false _softwareupdate:*:200:200:Software Update Service:/var/db/softwareupdate:/usr/bin/false _coreaudiod:*:202:202:Core Audio Daemon:/var/empty:/usr/bin/false _screensaver:*:203:203:Screensaver:/var/empty:/usr/bin/false _locationd:*:205:205:Location Daemon:/var/db/locationd:/usr/bin/false _trustevaluationagent:*:208:208:Trust Evaluation Agent:/var/empty:/usr/bin/false _timezone:*:210:210:AutoTimeZoneDaemon:/var/empty:/usr/bin/false _lda:*:211:211:Local Delivery Agent:/var/empty:/usr/bin/false _cvmsroot:*:212:212:CVMS Root:/var/empty:/usr/bin/false _usbmuxd:*:213:213:iPhone OS Device Helper:/var/db/lockdown:/usr/bin/false _dovecot:*:214:6:Dovecot Administrator:/var/empty:/usr/bin/false _dpaudio:*:215:215:DP Audio:/var/empty:/usr/bin/false _postgres:*:216:216:PostgreSQL Server:/var/empty:/usr/bin/false _krbtgt:*:217:-2:Kerberos Ticket Granting Ticket:/var/empty:/usr/bin/false _kadmin_admin:*:218:-2:Kerberos Admin Service:/var/empty:/usr/bin/false _kadmin_changepw:*:219:-2:Kerberos Change Password Service:/var/empty:/usr/bin/false _devicemgr:*:220:220:Device Management Server:/var/empty:/usr/bin/false _webauthserver:*:221:221:Web Auth Server:/var/empty:/usr/bin/false _netbios:*:222:222:NetBIOS:/var/empty:/usr/bin/false _warmd:*:224:224:Warm Daemon:/var/empty:/usr/bin/false _dovenull:*:227:227:Dovecot Authentication:/var/empty:/usr/bin/false _netstatistics:*:228:228:Network Statistics Daemon:/var/empty:/usr/bin/false _avbdeviced:*:229:-2:Ethernet AVB Device Daemon:/var/empty:/usr/bin/false _krb_krbtgt:*:230:-2:Open Directory Kerberos Ticket Granting Ticket:/var/empty:/usr/bin/false _krb_kadmin:*:231:-2:Open Directory Kerberos Admin Service:/var/empty:/usr/bin/false _krb_changepw:*:232:-2:Open Directory Kerberos Change Password Service:/var/empty:/usr/bin/false _krb_kerberos:*:233:-2:Open Directory Kerberos:/var/empty:/usr/bin/false _krb_anonymous:*:234:-2:Open Directory Kerberos Anonymous:/var/empty:/usr/bin/false _assetcache:*:235:235:Asset Cache Service:/var/empty:/usr/bin/false _coremediaiod:*:236:236:Core Media IO Daemon:/var/empty:/usr/bin/false _launchservicesd:*:239:239:_launchservicesd:/var/empty:/usr/bin/false _iconservices:*:240:240:IconServices:/var/empty:/usr/bin/false _distnote:*:241:241:DistNote:/var/empty:/usr/bin/false _nsurlsessiond:*:242:242:NSURLSession Daemon:/var/db/nsurlsessiond:/usr/bin/false _nsurlstoraged:*:243:243:NSURLStorage Daemon:/var/db/nsurlstoraged:/usr/bin/false _displaypolicyd:*:244:244:Display Policy Daemon:/var/empty:/usr/bin/false _astris:*:245:245:Astris Services:/var/db/astris:/usr/bin/false _krbfast:*:246:-2:Kerberos FAST Account:/var/empty:/usr/bin/false _gamecontrollerd:*:247:247:Game Controller Daemon:/var/empty:/usr/bin/false _mbsetupuser:*:248:248:Setup User:/var/setup:/bin/bash _ondemand:*:249:249:On Demand Resource Daemon:/var/db/ondemand:/usr/bin/false _xserverdocs:*:251:251:macOS Server Documents Service:/var/empty:/usr/bin/false _wwwproxy:*:252:252:WWW Proxy:/var/empty:/usr/bin/false _mobileasset:*:253:253:MobileAsset User:/var/ma:/usr/bin/false _findmydevice:*:254:254:Find My Device Daemon:/var/db/findmydevice:/usr/bin/false _datadetectors:*:257:257:DataDetectors:/var/db/datadetectors:/usr/bin/false _captiveagent:*:258:258:captiveagent:/var/empty:/usr/bin/false _ctkd:*:259:259:ctkd Account:/var/empty:/usr/bin/false _applepay:*:260:260:applepay Account:/var/db/applepay:/usr/bin/false _hidd:*:261:261:HID Service User:/var/db/hidd:/usr/bin/false _cmiodalassistants:*:262:262:CoreMedia IO Assistants User:/var/db/cmiodalassistants:/usr/bin/false _analyticsd:*:263:263:Analytics Daemon:/var/db/analyticsd:/usr/bin/false _fpsd:*:265:265:FPS Daemon:/var/db/fpsd:/usr/bin/false _timed:*:266:266:Time Sync Daemon:/var/db/timed:/usr/bin/false xiongweideMacBook-Pro:linux xiongwei$
查看将该文件的所属者改为root用户,如下:
先看一下该用户的所属组:
更改文件权限:
三组rwx分别代表:所属用户(user)、所属分组(group)、其他(other)。Linux文件权限使用
chmod
能够修改这三组权限。有两种设置方法。一种是数字,一种是符号。①、使用数字修改权限:
咱们来试一下改一下刚才新建的a.txt的权限,先看一下它目前的权限:咱们可以将其改为不可读不可写:
其中177分别代表user、group、other的权限对应值,对于这个文件而言root权限只有执行权限,但由于root是一个最高权限,所以这个例子举得有点不太恰当,得切成其它用户那就可以体现出这个权限的效果了,反正了解怎么修复权限是重点。②、使用符号改变权限:
对于修改文件的权限还有用这种符号,咱们还是基于新建的a.txt的user权限进行操作,目前它只有一个可执行权限:咱们用符号方式去掉其执行权限,如下:
但是发现貌似group和other的可执行权限也木有了:
可见该方法是会修改user、group、other三个权限的。然后再给它加回来执行权限:
然后再给它加一个可读权限:
这个方法目前是对user、group、other进行统一更改的,那如果只想对其中一个进行更改呢,就可以使用下面的方法:
咱们试一下只给user去掉可读权限,如下:
这块比较简单,到时需要的时候照着改就成。
su和sudo:
su : 在已登陆的终端(命令行)会话中登陆到另一个用户。即 切换用户。
su [切换的用户名] 未输入用户名,默认切换到root用户
咱们来试一下:su 和 su -是存在区别的,两者的区别是,前者只切换了身份,而后者相当于重新登陆。su - 重新登陆后目录切换到用户配置的工作目录。什么意思,咱们用“su -”来试一下就明白了:
sudo: 用户普通用户使用root权限来执行命令(不切换用户)。即临时提升用户权限为root权限,比较简单,在MAC上谨慎用su来提权,因为如果用su之后的任何修改系统是不涉防的,所以比较危险,遇到没权限的文件就用sudo来临时提下权既可。
包管理器:
就是用来装软件用的,记录一下就成:
Mac: brew
Ubuntu: apt
Centos: yum
VI/VIM:
关于它基本也是熟能生巧,据说大神都是用它来编程的。。对于我来说知道基本的使用就成了,下面简单回顾一下,反正也记不住,下图已经详细进行了介绍:
总的来说是分为三种模式,分别是命令模式,输入模式和底线命令模式,如下:
命令模式
用户刚刚启动 vi/vim,便进入了命令模式。
此状态下敲击键盘动作会被Vim识别为命令,而非输入字符。比如我们此时按下i,并不会输入一个字符,i被当作了一个命令。
常用的命令:
i 切换到输入模式,以输入字符。
x 删除当前光标所在处的字符。
: 切换到底线命令模式,以在最底一行输入命令。
输入模式
在输入模式中,可以使用以下按键:
字符按键以及Shift组合
,输入字符ENTER
,回车键,换行BACK SPACE
,退格键,删除光标前一个字符DEL
,删除键,删除光标后一个字符方向键
,在文本中移动光标HOME/END
,移动光标到行首/行尾Page Up/Page Down
,上/下翻页Insert
,切换光标为输入/替换模式,光标将变成竖线/下划线ESC
,退出输入模式,切换到命令模式
底线命令模式
在命令模式
下按下:(英文冒号)就进入了底线命令模式。
q
退出程序w
保存文件wq
保存并退出q! wq!
!:表示强制
iptables防火墙:【了解既可】
1、Ubuntu 默认有装iptables,可通过which iptables确认
2、Ubuntu默认没有iptables配置文件,可通过iptables-save > /etc/iptables.up.rules生成
3、读取配置并生效可以通过 iptables-restore < /etc/iptables.up.rules
4、vim /etc/network/interfaces 增加
pre-up iptables-restore < /etc/iptables.up.rules #启动时应用防火墙
post-down iptables-save > /etc/iptables.up.rules #关闭时保存防火墙设置,以便下次启动时使用
iptables-save > /etc/iptables.up.rules 内容类似:
# Generated by iptables-save v1.6.0 on Mon Aug 27 12:34:05 2018
*filter
# DROP 表示关闭、ACCPET表示允许
:INPUT DROP [11:722]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [29:2664]
#开发 22和80801 端口
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT
COMMIT
# Completed on Mon Aug 27 12:34:05 2018
常用操作:
#查看当前防火墙配置并显示规则行号
iptables -L --line-numbers
#开启 8080 端口
iptables -A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT
#关闭 8888 端口
iptables -A INPUT -p tcp -m tcp --dport 8888 -j DROP
#删除 1 号 规则(行号)
iptables -D INPUT 1