Mae VpnService Android yn cysylltu ond nid oes pecynnau yn cyrraedd y rhwydwaith
Twnnel i fyny a thudalennau'n dal i fethu: gwiriwch y modd darllen, amddiffyniad socket, cefnogaeth TCP a'r rhestr llwybrau cyn beio'r gweinydd VPN.
Mae'r twnnel yn codi, mae'r eicon allwedd yn ymddangos, ac mae pob cais yn y porwr yn dal i ddod i ben. Mewn ap VpnService mae'r cyfuniad hwnnw fel arfer yn golygu bod y ddolen ddarllen yn fyw a bod yr hanner allbwn wedi torri, nid bod y gweinydd wedi gwrthod yr ysgwyd llaw. Mae Android eisoes wedi creu'r rhyngwyneb, wedi symud traffig yr ap iddo, ac wedi rhoi disgrifydd ffeil i'ch proses. Popeth ar ôl y disgrifydd hwnnw yw eich cod, ac mae un alwad ar goll yn ddigon i lyncu'r ffrwd gyfan.
Yr hyn y mae'r system yn ei roi i chi, a'r hyn nad yw
Mae establish() yn dychwelyd ParcelFileDescriptor ar gyfer rhyngwyneb tun. Mae'r system yn ysgrifennu pecynnau IP allanol iddo ac yn disgwyl i'ch proses eu darllen, penderfynu i ble maen nhw'n mynd, a'u hanfon trwy socket cyffredin. Nid oes anfon cnewyllyn oddi tano, felly pan nad oes neb yn darllen, mae'r pecynnau'n cael eu gollwng ac nid yw cownteri'r rhyngwyneb byth yn symud.
Dechreuwch drwy gyfrif yn hytrach na dyfalu. Cynyddwch gowntwr ar bob darlleniad llwyddiannus a chofnodwch gyrchfan a phrotocol y pecynnau cyntaf. Os yw'r cownter yn aros ar sero tra bod traffig yn cael ei gynhyrchu, mae'r nam yn uwch na'ch cod anfon, sy'n culhau'r chwilio i ffurfweddiad y builder a'r modd darllen. Os yw'r cownter yn symud a'r porwr yn dal i fethu, mae'r nam yn y llwybr anfon neu ar y ffordd yn ôl.
Darlleniad blocio sy'n penderfynu a yw'r ddolen yn symud
Mae setBlocking(true) yn rhoi'r disgrifydd mewn modd blocio ac wedi bodoli ers API 21. Ar ryddhadau hŷn y gwaith o amgylch yw helpwr JNI bach sy'n clirio O_NONBLOCK gyda fcntl ar y disgrifydd crai. Mae'r modd yn bwysig oherwydd ei fod yn penderfynu beth y caniateir i ddarlleniad heb becyn yn aros ei wneud.
Mewn modd nad yw'n blocio mae'r darlleniad hwnnw'n dychwelyd ar unwaith gyda gwerth negyddol, ac mae dolen sy'n anwybyddu'r canlyniad yn troi craidd heb symud unrhyw draffig o gwbl. Mewn modd blocio mae'r darlleniad yn aros, sef yr hyn y mae edau anfon eisiau, ond wedyn ni ellir torri ar draws yr edau mwyach. Cau'r disgrifydd yw'r ffordd a gefnogir i wneud i'r darlleniad fethu fel y gall y ddolen adael. Mae lladd y broses neu dorri ar draws yr edau yn lle hynny yn gallu gadael y cychwyn nesaf gyda disgrifydd nad yw'n cyfateb i'r rhyngwyneb mwyach.
Darllenwch un pecyn y gelwad i ffrwydrofa a faint MTU y rhyngwyneb, a thriniwch sero neu ddychweliad negyddol fel gwall yn hytrach na phecyn gwag.
protect() cyn yr anfoniad cyntaf, nid ar ei ôl
Rhaid amddiffyn pob socket sy'n cario pecyn wedi'i grynhoi yn gyntaf. Mae socket heb ei amddiffyn yn ufuddhau i'r un rheolau llwybro y gwnaethoch eu gosod, felly mae ei becynnau'n mynd yn ôl i'r twnnel ac mae eich dolen ddarllen eich hun yn eu codi eto. Yna mae'r twnnel yn anfon ei allbwn ei hun am byth, ac o'r tu allan mae'n edrych fel cysylltiad sy'n agor ac nad yw byth yn ateb.
Y drefn yw protect, yna connect neu bind, yna send. Gall galw protect ar ôl connect adael y penderfyniad llwybr cynharach yn ei le, felly mae'r socket yn dal i ddefnyddio'r llwybr anghywir er bod yr alwad wedi dychwelyd true. Gwiriwch y boolean y mae'n ei ddychwelyd a methwch yn uchel pan fydd yn false yn hytrach na cherdded i anfoniad na all weithio.
Gwall caniatâd o sendto ar socket na chyffyrddodd â protect() erioed yw arwydd arferol y camgymeriad hwn.
Nid yw'r sampl UDP yn cario HTTPS
Mae'r sampl anfon y mae'r rhan fwyaf o diwtorialau'n ei gopïo yn trin UDP a dim arall. Mae TCP angen ysgwyd llaw, rhifau dilyniant, cydnabyddiaethau ac aildrosglwyddo, ac nid yw dolen sy'n copïo llwythi rhwng disgrifydd tun a socket yn darparu'r un ohonynt. Dyna pam y gall ymholiad DNS dros UDP basio tra bod pob cais HTTPS yn stond. Naill ai rhedwch stac TCP yn null defnyddiwr neu rhowch gysylltiadau i brocsi lleol sy'n terfynu TCP ar y ddyfais ac yn anfon y ffrwd ymlaen.
Profwch y rhaniad cyn ailysgrifennu unrhyw beth: anfonwch un ymholiad UDP ac agorwch un cysylltiad TCP i'r un gwesteiwr. Os yw'r llwybr UDP yn gweithio ac mae'r llwybr TCP yn hongian ar y SYN cyntaf, y cod anfon sy'n gyfrifol ac nid y gweinydd. Mae'r un gymhariaeth honno'n arbed llawer o amser a dreulir yn darllen logiau gweinydd nad ydynt yn cynnwys unrhyw beth defnyddiol.
Mae'r rhestr llwybrau a hidlwyr fesul ap yn cyfyngu ar yr hyn a welwch
Mae addAddress, addRoute ac addDns yn diffinio'r hyn y mae'r system yn ei anfon i'r twnnel. Nid yw cyrchfan y tu allan i'r rhestr llwybrau byth yn cyrraedd eich disgrifydd, felly ni fydd unrhyw faint o resymeg anfon yn ei thrwsio. Cofnodwch yr alwadau builder a wnewch a'u cymharu â'r cyfeiriadau y mae'r ap yn ceisio eu cyrraedd mewn gwirionedd.
Mae gan ddewis fesul ap ei lawr ei hun: mae addAllowedApplication ac addDisallowedApplication angen API 21, ac ar ryddhadau hŷn nid yw'r dulliau'n bodoli o gwbl. Ni all dyluniad sy'n hidlo yn ôl pecyn redeg yno o gwbl.
Mae ailsefydlu yn gadael disgrifwyr hen ffasiwn ar ôl
Mae galw establish() eto yn dychwelyd disgrifydd newydd ac yn cau'r rhyngwyneb blaenorol. Mae'r hen ddisgrifydd bellach yn annilys, felly mae edau sy'n dal i flocio arno yn cael gwall, ac efallai y bydd angen disodli socedi a grëwyd ar gyfer yr hen lwybr. onRevoke yw'r alwad yn ôl ar gyfer twnnel y mae'r defnyddiwr neu'r system wedi'i gymryd. Mae cadw'r cylch bywyd mewn un perchennog, sy'n stopio'r darllenydd cyn ailsefydlu, yn atal y rhan fwyaf o'r cyflyrau cysylltiedig-ond-marw.
Darllenwch bob gwall yn ôl y cam y mae'n perthyn iddo. Mae ailosod cysylltiad o recvfrom yn golygu bod y pen pell wedi cau tra oedd eich cod yn dal i ddarllen. Mae gwall cyfeiriad drwg yn pwyntio at barcio pennawd neu fyg mewn offset, nid at y rhwydwaith.
Trefn y gwaith: modd blocio ymlaen, un pecyn y darlleniad, pennawd wedi'i barcio, socket wedi'i amddiffyn, llwyth wedi'i anfon, cau'n lân wrth drosglwyddo, a rhestr llwybrau sy'n gorchuddio'r gyrchfan.