|
#
netsh firewall
set opmode mode = ENABLE
Socks5的工作程序
1.客戶端向Socks5服務(wù)器發(fā)出請(qǐng)求信息。
2.Socks5應(yīng)答
3.客戶端接到應(yīng)答后發(fā)送向Socks5服務(wù)器發(fā)送目的服務(wù)器的ip和端口
4.Socks5與目的服務(wù)器連接
5.Socks5將客戶端發(fā)出的信息傳到目的服務(wù)器,將目的服務(wù)器發(fā)出的信息傳到客戶端。代理完成。
由于網(wǎng)上的信息傳輸都是運(yùn)用tcp或udp進(jìn)行的,所以使用socks5代理可以辦到網(wǎng)上所能辦到的一切,而且目的服務(wù)器不會(huì)反查到客戶端的真實(shí)ip,既安全又方便 sock5支持UDP和TCP,但兩種代理是有區(qū)別的,以下分類(lèi)說(shuō)明
如何用代理TCP協(xié)議
1.向服務(wù)器的1080端口建立tcp連接。
2.向服務(wù)器發(fā)送 05 01 00 (此為16進(jìn)制碼,以下同)
3.如果接到 05 00 則是可以代理
4.發(fā)送 05 01 00 01 + 目的地址(4字節(jié)) + 目的端口(2字節(jié)),目的地址和端口都是16進(jìn)制碼(不是字符串!!)。
例202.103.190.27 - 7201 則發(fā)送的信息為:05 01 00 01 CA 67 BE 1B 1C 21 (CA=202
67=103 BE=190 1B=27 1C21=7201)
5.接受服務(wù)器返回的自身地址和端口,連接完成
6.以后操作和直接與目的方進(jìn)行TCP連接相同。
如何用代理UDP連接
1.向服務(wù)器的1080端口建立udp連接
2.向服務(wù)器發(fā)送 05 01 00
3.如果接到 05 00 則是可以代理
4.發(fā)送 05 03 00 01 00 00 00 00 + 本地UDP端口(2字節(jié))
5.服務(wù)器返回 05 00 00 01 +服務(wù)器地址+端口
6.需要申請(qǐng)方發(fā)送 00 00 00 01 +目的地址IP(4字節(jié))+目的端口 +所要發(fā)送的信息
7.當(dāng)有數(shù)據(jù)報(bào)返回時(shí) 向需要代理方發(fā)出00 00 00 01 +來(lái)源地址IP(4字節(jié))+來(lái)源端口 +接受的信息
注:此為不需要密碼的代理協(xié)議,只是socks5的一部分,完整協(xié)議請(qǐng)查看RFC1928
名字很滑稽,使用方法與 pgsql for python使用方式有所不同 ,但都 遵循DB2.0 http://initd.org/psycopg/docs/usage.html 參考文檔
>>> cur.execute("INSERT INTO foo VALUES (%s)", ("bar",)) # correct 注意 %s不能攜帶''字符串定界符;參數(shù)tuples必須添加末尾 ,
>>> cur.execute( ... """INSERT INTO some_table (an_int, a_date, a_string) ... VALUES (%s, %s, %s);""", ... (10, datetime.date(2005, 11, 18), "O'Reilly")) 參數(shù)數(shù)組傳遞方式
>>> cur.execute( ... """INSERT INTO some_table (an_int, a_date, another_date, a_string) ... VALUES (%(int)s, %(date)s, %(date)s, %(str)s);""", ... {'int': 10, 'str': "O'Reilly", 'date': datetime.date(2005, 11, 18)}) 參數(shù)哈希傳遞方式
cur.execute('insert into table_a values(%s)',(psycopg2.Binary(file.read()),)) 插入二進(jìn)制數(shù)據(jù)
TileCache默認(rèn)是Disk緩存Tile數(shù)據(jù),存儲(chǔ)和檢索的效率遠(yuǎn)不及數(shù)據(jù)庫(kù),所以要開(kāi)發(fā)數(shù)據(jù)庫(kù)Cache,讀完TileCache代碼,發(fā)現(xiàn)其系統(tǒng)結(jié)構(gòu)設(shè)計(jì)的還算可以 tilecache-2.10\TileCache\Caches目錄下就是TileCache自帶的Cache類(lèi)型,Cache有個(gè)抽象基類(lèi),我的數(shù)據(jù)Cache只要實(shí)現(xiàn)這些Cache的接口便能完成到數(shù)據(jù)庫(kù)的Tile存取。
1 class Cache (object): 2 def __init__ (self, timeout = 30.0, stale_interval = 300.0, readonly = False, **kwargs): 3 self.stale = float(stale_interval) 4 self.timeout = float(timeout) 5 self.readonly = readonly 6 7 def lock (self, tile, blocking = True): 8 start_time = time.time() 9 result = self.attemptLock(tile) 10 if result: 11 return True 12 elif not blocking: 13 return False 14 while result is not True: 15 if time.time() - start_time > self.timeout: 16 raise Exception("You appear to have a stuck lock. You may wish to remove the lock named:\n%s" % self.getLockName(tile)) 17 time.sleep(0.25) 18 result = self.attemptLock(tile) 19 return True 20 21 def getLockName (self, tile): 22 return self.getKey(tile) + ".lck" 23 24 def getKey (self, tile): 25 raise NotImplementedError() 26 27 def attemptLock (self, tile): 28 raise NotImplementedError() 29 30 def unlock (self, tile): 31 raise NotImplementedError() 32 33 def get (self, tile): 34 raise NotImplementedError() 35 36 def set (self, tile, data): 37 raise NotImplementedError() 38 39 def delete(self, tile): 40 raise NotImplementedError()
接口夠簡(jiǎn)單了吧 ,最主要的實(shí)現(xiàn)的 是get,set,getKey這3個(gè)主要接口 tilecache.cfg的Cache.type設(shè)置為DB_POSTGRES
考慮將shp格式的地圖數(shù)據(jù)發(fā)布到webgis上去的想法有一段時(shí)間了,正好有空閑時(shí)間便忙碌開(kāi)來(lái),沒(méi)想到期間遇到了諸多的問(wèn)題
1.開(kāi)發(fā)工具: Geoserver,Openlayer,Ext-js,Postgres/Postgis,Python2.6,PIL,TileCache 2.地圖數(shù)據(jù) 我的地圖數(shù)據(jù)是08年的全國(guó)地圖,按每個(gè)省市分隔開(kāi)來(lái),每個(gè)省市又分了若干個(gè)圖層文件,格式是mapinfo的Tab,容量10G 由于沒(méi)有全國(guó)大比例圖,在偶然的一個(gè)機(jī)會(huì)從網(wǎng)上下載到一份C/S的監(jiān)控系統(tǒng),沒(méi)想到安裝目錄內(nèi)就有一份全國(guó)圖,就是比例不高。 3.處理過(guò)程 1.Tab轉(zhuǎn)換成shp: Ogr工具可以完成這兩種格式的轉(zhuǎn)換,編寫(xiě)python腳本可以輕易處理完 在轉(zhuǎn)換數(shù)據(jù)之前需要提醒的是,發(fā)現(xiàn)在處理多邊形圖層時(shí),這個(gè)多邊形圖層并不是簡(jiǎn)單的多邊形,也就是那種mapinfo允許存在polygon和pline的圖層,這將導(dǎo)致之后的導(dǎo)入空間數(shù)據(jù)庫(kù)的失敗,因?yàn)閜ostgis要求每個(gè)圖層數(shù)據(jù)類(lèi)型必須是一致的,不能存在多種類(lèi)型,所以編寫(xiě)mapbasic腳本,將這些pline對(duì)象從這多邊形圖層中剔去即可。 2.數(shù)據(jù)校驗(yàn): 這個(gè)過(guò)程非常重要,任何提供的的矢量數(shù)據(jù)都有可能存在錯(cuò)誤數(shù)據(jù),所以第一步必須要修復(fù)這些可能存在的錯(cuò)誤,工具就是ArcGis,使用其工具對(duì)每個(gè)省市的每個(gè)圖層文件進(jìn)行修復(fù)。 3.導(dǎo)入空間數(shù)據(jù)庫(kù): 編寫(xiě)腳本,將shp數(shù)據(jù)轉(zhuǎn)成sql文件,此時(shí)必須注意空間數(shù)據(jù)庫(kù)的字符編碼與sql數(shù)據(jù)字符編碼要吻合或者能夠自動(dòng)轉(zhuǎn)換。pg2sq由于轉(zhuǎn)換成sql時(shí),由于shp數(shù)據(jù)中某些圖層表存儲(chǔ)的字符編碼不統(tǒng)一導(dǎo)致產(chǎn)生的非法的sql數(shù)據(jù),所以必須對(duì)這些數(shù)據(jù)進(jìn)行修正,并采用ultraedit將數(shù)據(jù)進(jìn)行轉(zhuǎn)碼成數(shù)據(jù)的字符集類(lèi)型,我使用的是utf-8. 4.數(shù)據(jù)分離: 由于提供的全國(guó)地理數(shù)據(jù)是沒(méi)有根據(jù)應(yīng)用來(lái)分層的,所有的道路都合在同一個(gè)叫road的圖層內(nèi),然后通過(guò)屬性來(lái)區(qū)分道路的級(jí)別,由于我們?cè)诳刂骑@示道路時(shí)是需要分層分級(jí)別的,所以必須將這些數(shù)據(jù)要分離成不同的道路圖層,道路共10級(jí)別(0-9),編寫(xiě)腳本將每個(gè)省市的道路切割成road_?10級(jí)道路層(select into即可搞定)。 同樣,除了道路之外還有其他的比如河流,POI對(duì)象等都需要進(jìn)行分割到不同圖層以便更精確的現(xiàn)實(shí)控制。 5.配置Geoserver: 數(shù)據(jù)都有了,接下來(lái)就是配置繪制引擎了。Geoserver提供WFS,WMS服務(wù),性能一般,由于是java開(kāi)發(fā)的。不管3721,配置了最新的I5主機(jī),將java虛擬機(jī)的內(nèi)存設(shè)置的最大,將postgis的數(shù)據(jù)庫(kù)內(nèi)存也足夠調(diào)大。手工添加了1,2個(gè)圖層到geoserver,preview一下,ok! 接下來(lái)編寫(xiě)控制這些圖層的SLD了,這些花了好些時(shí)間學(xué)習(xí)和開(kāi)發(fā)(學(xué)習(xí)sld對(duì)我以前開(kāi)發(fā)嵌入式地圖引擎風(fēng)格配置也是一種幫助,之后的嵌入式地圖引擎也全部使用sld進(jìn)行配置了!) 由于全國(guó)數(shù)據(jù)分31個(gè)省市,每個(gè)省市都配置了21個(gè)圖層,所以要人工11加到geoserver還真是很大的問(wèn)題,不過(guò)沒(méi)關(guān)系,有python在手,然后對(duì)geoserver的配置文件研究了一把便寫(xiě)了腳本將幾百個(gè)圖層全加了進(jìn)去,然后將這些圖層按省市進(jìn)行分組,再次Preview,ok! 6.Cache Tile生成: 使用過(guò)GeoWebCache,發(fā)現(xiàn)很多地方實(shí)在不好理解,幸好找到了TileCache,代碼也容易修改,研讀了TileCache代碼之后修改了N處地方,把效率提高了10倍以上?,F(xiàn)在的問(wèn)題在于Tilecache實(shí)現(xiàn)了Disk Cache,Memory Cache,但就是沒(méi)有DB cache,每個(gè)tile將創(chuàng)建一個(gè)文件,如果這些文件很小,有的甚至才幾十字節(jié)也要浪費(fèi)一個(gè)文件塊空間,效率不高,如果采用db的話空間就能節(jié)省很多,等以后有了時(shí)間自己編寫(xiě)一個(gè)后端為postgres的Tile Cache吧。
Tile Cache生成有些問(wèn)題要注意: 1. 空白tile: 由于我設(shè)置的繪制設(shè)置的BBox非常大,所以在繪制的時(shí)候有些空白區(qū)域也將提交給geoserver進(jìn)行處理,這樣浪費(fèi)了處理時(shí)間,同時(shí)這些產(chǎn)生的小規(guī)格圖塊大大占據(jù)了磁盤(pán)空間,所以修改的代碼將不存儲(chǔ)這些空白tile,僅僅存儲(chǔ)這些tile的文件名稱(chēng),而不保存內(nèi)容 2. tilecache的Resolutions,ZoomLevels,BBox和Openlayers的屬性必須一樣,否則Opnelayers無(wú)法顯示正確的tile 3. tile相交檢測(cè): 同樣是空白區(qū)域的繪制,如果每次都提交給geoserver的話,geoserver將根據(jù)配置的layer去相交并繪制一次,這就完全沒(méi)有必要的,我的解決方式就是提前將31個(gè)省市產(chǎn)生他們的MBR,然后再tile進(jìn)行提交給geoserver之前,將請(qǐng)求的tile的bbox與這些省市的mbr進(jìn)行相交測(cè)試,只有相交的圖層才送入geoserver繪制 4. 大網(wǎng)格繪制: 每次以256×256的規(guī)格給geoserver繪制全國(guó)圖的話效率實(shí)在太低,之后修改成2048×2048規(guī)格,整體的繪制效率上升了n倍,繪制完了之后采用split_tile.py將這些大塊切割成256規(guī)格的小塊,必須注意產(chǎn)生的序號(hào)
寫(xiě)得好累
一下處理過(guò)程需要在python2.5與2.6之間切換
Pgsql8.3.5
postgis1.5
tilecache 2.10
geoserver2.0
openlayers
ext-js
django
1.
openlayer顯示地圖無(wú)法顯示正確的比例尺
在訪問(wèn)地圖時(shí)設(shè)置地圖顯示單位必須為 units:'degrees'
2. 圖層文字標(biāo)注出現(xiàn)亂碼和重復(fù)繪制多個(gè)相同名稱(chēng)
Sld設(shè)置的group=true似乎沒(méi)有起作用
layer = new OpenLayers.Layer.WMS( "FirstMap","http://localhost:8080/geoserver/wms",{},{singleTile: true, ratio: 1})
必須設(shè)置紅色部分的參數(shù),能保證文字不被重復(fù)顯示
但是在使用tilecache.py預(yù)緩沖圖塊時(shí)("http://localhost:9000/tilecache/tilecache.py"),添加了以上紅色參數(shù)之后導(dǎo)致無(wú)法顯示地圖。
SingleTile:true 參數(shù)是作為geoserver的附加屬性由openlayer傳遞到服務(wù)器,
所以考慮將此參數(shù)通過(guò)tilecache.cfg傳遞到geoserver是否能夠起到相同效果?
發(fā)現(xiàn)使用了signleTile之后,openlayers將不進(jìn)行塊的緩沖,而是每次請(qǐng)求都到geoserver上去獲取,抓包發(fā)現(xiàn)singleTile開(kāi)啟的話,請(qǐng)求時(shí)將不傳遞width/height參數(shù),直接請(qǐng)求bbox大小的地理區(qū)域,每次移動(dòng)地圖將重新加載整個(gè)區(qū)域,效率低下;
但是關(guān)閉singleTile的話,依次連續(xù)請(qǐng)求多個(gè)網(wǎng)格塊,默認(rèn)是256x256,導(dǎo)致有些圖層比如背景層1024×1024的話將請(qǐng)求4x4個(gè)網(wǎng)格塊,每個(gè)塊都將繪制背景的文本標(biāo)識(shí),因?yàn)檫@些塊是離散繪制的所以顯示在地圖上的話將是重復(fù)的文本顯示出來(lái)了,所以避免這個(gè)問(wèn)題只有如下解決:
1.
放大網(wǎng)格的大小規(guī)格,使一定的地理范圍盡可能的處在一個(gè)網(wǎng)格內(nèi)被繪制
目前這種方式似乎是最佳方式,tilecache 默認(rèn)tile規(guī)格是256*256,在繪制全國(guó)圖的時(shí)候設(shè)置1024*1024方式去請(qǐng)求geoserver,然后使用split_tile.py切割土塊即可。
2.
控制這些層的顯示屬性,限制只有在某些比例尺時(shí)被顯示
3.
手工編輯地圖數(shù)據(jù),合并多邊形對(duì)象,這樣就可以防止重復(fù)繪制多邊形的名稱(chēng)標(biāo)注,導(dǎo)致一個(gè)省份名稱(chēng)繪制多次
Tilecache為了支持apache訪問(wèn),必須安裝到python/lib/目錄下,并且tilecache.cfg也在這個(gè)安裝目錄下。
Tilecache.cfg修改之后必須重新啟動(dòng)apache服務(wù)
如果geoserver實(shí)時(shí)繪制的話允許同時(shí)傳遞多個(gè)層名稱(chēng)給geoserver進(jìn)行繪制
new
OpenLayers.Layer.WMS( "FirstMap",
"http://localhost:8080/geoserver/wms",
{ layers:’shanghai,china,…’})
如果tilecahce加載tile網(wǎng)格塊的話,layers屬性不能傳遞多個(gè)圖層,因?yàn)槎鄠€(gè)圖層就是返回多個(gè)tile塊,只有在tilecache.cfg中配置多個(gè)layer名稱(chēng)
[east_china]
type=WMSLayer
url=http://localhost:8080/geoserver/wms
layers=shanghai,jiangshu,zejiang
extension=png
resolutions=0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.00137329101,0.0006,0.0003,0.00015,0.000075,0.000035,0.000018,0.000009,0.0000045
bbox=70,10,130,60
優(yōu)化批量自動(dòng)化繪制地圖
1.
tilecache_seed.py提交layers給geoserver 時(shí),如果提交全國(guó)所有layers,geoserver將處理每個(gè)layer,即使layer與當(dāng)前可見(jiàn)地理區(qū)域不想交,但還是會(huì)被循環(huán)處理;所以必須改寫(xiě)tilecahe_seed.py程序,檢測(cè)只有相交的圖層傳送給geoserver渲染。
改寫(xiě)部分在TileCache/Layers/WMS.py中,
def
renderTile(self, tile):
wms = WMSClient.WMS( self.url, {
"bbox": tile.bbox(),
"width": tile.size()[0],
"height": tile.size()[1],
"srs": self.srs,
"format": self.mime_type,
"layers": self.layers,
}, self.user, self.password)
tile.data, response = wms.fetch()
return tile.data
self.layers參數(shù)就是tilecache.cfg中參數(shù)layers定義的層列表,所以只需要修改這個(gè)參數(shù)即可。
處理方式:
將tile.bbox()的地理區(qū)間與數(shù)據(jù)庫(kù)中的省市層最大mbr進(jìn)行相交測(cè)試,只有相交的才提交給geoserver進(jìn)行處理。
修改之后
測(cè)試:
將網(wǎng)格規(guī)格調(diào)整為256*256,繪制east_china圖層第7顯示級(jí)別,花銷(xiāo)48秒
修改代碼如下:
def
isIntersect(self,rc1,rc2):
if rc1[2] < rc2[0] or rc1[3] < rc2[1]
or rc1[0] > rc2[2] or rc1[1] > rc2[3]:
return False
return True
def renderTile(self, tile):
import sys,string
sys.path.append('c:/')
import cities_mbr
layers = self.layers.split(',')
newLayers=[]
for layer in layers:
rc = cities_mbr.G_CITIES_MBR[layer]
rc2 = tile.bbox().split(',')
rc2 = map(float,rc2)
if self.isIntersect(rc,rc2):
newLayers.append(layer)
layers = string.join(map(str,newLayers),',')
if len(newLayers) == 0: #no any
insercted layer
layers='china:china_blank_layer' #here i select shanghai as empty city to
fill
print layers
wms = WMSClient.WMS( self.url, {
"bbox": tile.bbox(),
"width": tile.size()[0],
"height": tile.size()[1],
"srs": self.srs,
"format": self.mime_type,
#"layers": self.layers,
"layers": layers,
}, self.user, self.password)
print 'x*'*20
print self.url,tile.bbox(),layers
#import sys
#sys.exit(0);
tile.data, response = wms.fetch()
return tile.data
注意以上紅色代碼,當(dāng)檢索不能匹配任何圖層時(shí),需要geoserver返回空白圖塊,self.layers必須設(shè)置一個(gè)數(shù)據(jù)庫(kù)中可用的圖層名稱(chēng),這個(gè)圖層只是為了繪制空白塊的,所以可以在postgis中創(chuàng)建一個(gè)point層即可或者一個(gè)空層,然后添加一個(gè)遠(yuǎn)離中國(guó)地理區(qū)域的一個(gè)點(diǎn)即可.
2.
顯示比例越小的時(shí)候,繪制地圖需要更多的時(shí)間,那是由于顯示的越大繪制的圖層就越多。
要使多臺(tái)機(jī)器同時(shí)分工繪制地圖的話,
可以按層進(jìn)行分割處理和劃分經(jīng)緯度的方式進(jìn)行。前者適用與高比例尺的顯示,后者就是小比例尺的顯示。
小顯示比例時(shí),tilecache將圖層進(jìn)行網(wǎng)格化處理,由西至東,由下至上。所以提交給處理機(jī)器以不同的bbox即可,處理完成之后再將這些圖塊重新進(jìn)行編號(hào)即可。()
3.
在低縮放比的情況下放大tile的規(guī)格,默認(rèn)是256×256,將其設(shè)置為256×n大小,這樣可以提高每次請(qǐng)求的效率,之后再將圖塊切割為256×256大小的png圖塊。 這就要求geoserver的sld關(guān)閉
<vendor-group>true</vendor-group>開(kāi)關(guān)
測(cè)試:
將網(wǎng)格規(guī)格調(diào)整為1024*1024,繪制east_china圖層第7顯示級(jí)別,花銷(xiāo)30秒
將網(wǎng)格規(guī)格調(diào)整為256*256,繪制east_china圖層第7顯示級(jí)別,花銷(xiāo)200秒
圖像擴(kuò)大了16倍,時(shí)間縮短了6倍
大圖塊產(chǎn)生之后切割為小圖塊,需要重新索引文件編號(hào)。
設(shè)A規(guī)格圖塊和B規(guī)格圖塊(A*4=B),如果A繪制需要產(chǎn)生400列(0-399),400行(0-399),那B只需要產(chǎn)生100列100行。
Tilecache預(yù)處理數(shù)據(jù)存儲(chǔ)方式:
圖塊數(shù)據(jù)繪制時(shí)按照經(jīng)度從西到東,維度從南到北的順序依次繪制出網(wǎng)格圖塊。
每一列的圖塊都創(chuàng)建出一個(gè)目錄,從下標(biāo)0開(kāi)始。
繪制方式:
For(x=0;x<columns;x++){
For(y=0;y<rows;y++){
Draw_tile()
}
}
層名稱(chēng)/縮放級(jí)別/000/000/列編號(hào)/000/000/行圖塊文件.png
Tilecache的數(shù)據(jù)存儲(chǔ)目錄在刪除時(shí)必須注意停止apache服務(wù)
Apache提供tile服務(wù)時(shí)將自動(dòng)使用python2.6下的tilecache代碼
操作數(shù)據(jù)庫(kù)是采用的是pgpostgresql,目前只支持python2.5,所以必須先注視掉c:/python2.6, 打開(kāi)c:/python2.5
在實(shí)際的cache生成過(guò)程中遇到大地理范圍和多顯示比例的問(wèn)題時(shí),生成tile cache的耗時(shí)是個(gè)頭大的問(wèn)題,越低比例尺的繪制耗時(shí)將成幾何倍數(shù)上升,如果要繪制1:1000的全國(guó)圖的話,完成工作一臺(tái)主機(jī)可能需要幾個(gè)月的時(shí)間,tilecache默認(rèn)的請(qǐng)求tile規(guī)格是256×256,性能實(shí)在太低,所以提高每次向geoserver請(qǐng)求圖塊的規(guī)格來(lái)稍微提高速度,目前我采用2048×2048。 但openlayers里面256×256是最佳的cache規(guī)格,所以tilecache產(chǎn)生的tile必須進(jìn)行切割成256規(guī)格
1 # -*- coding:utf-8 -*- 2 3 #切割大地圖塊到小圖塊,重新索引圖塊文件目錄 4 5 #層名稱(chēng)/縮放級(jí)別/000/000/列編號(hào)/000/000/行圖塊文件.png 6 7 import sys, traceback,threading,time,struct,os,os.path,shutil,distutils.dir_util,array,base64,zlib 8 import PIL,Image 9 10 g_layerName='east_china' 11 12 srcTiles={'path':'','size':(1024,1024)} 13 destTiles={'path':'','size':(256,256)} 14 15 #layerName - 處理的地圖層名,在tilecache.cfg中定義 16 #scale - 顯示級(jí)別 17 #tileDir - 圖塊存儲(chǔ)目錄 18 #destDir - 切割圖塊存儲(chǔ)目錄 19 #tilesizeFrom - 當(dāng)前圖塊規(guī)格 20 #tilesizeTo - 目標(biāo)圖塊規(guī)格 21 #注意: 維度從下至上遞增 22 #一個(gè)大網(wǎng)格塊列切割成多列,行且歌城多行 23 def splitTile(layerName,scale,tilesDir,destDir,tilesizeFrom=(1024,1024),tilesizeTo=(256,256)): 24 xcols = tilesizeFrom[0]/tilesizeTo[0] 25 xrows = tilesizeFrom[1]/tilesizeTo[1] 26 27 path2 = "%s/%s/%02d/000/000"%(destDir,layerName,scale) 28 if not os.path.exists(path2): 29 os.makedirs(path2) 30 path1 = "%s/%s/%02d/000/000"%(tilesDir,layerName,scale) 31 cols = map(int,os.listdir(path1)) 32 for col in cols: #1列要切割成n列 33 path1 = "%s/%s/%02d/000/000/%02d/000/000"%(tilesDir,layerName,scale,col) 34 for x in range(xcols): 35 newcol = col*xcols + x 36 path2 = "%s/%s/%02d/000/000/%02d/000/000"%(destDir,layerName,scale,newcol) #大土快可以切割成多列 37 if not os.path.exists(path2): 38 os.makedirs(path2) 39 #print path1 40 files = os.listdir(path1) #list columns 41 for file in files: 42 name,ext = file.split('.') 43 path3 = "%s/%s/%02d/000/000/%02d/000/000/%s"%(tilesDir,layerName,scale,col,file) # 44 img = Image.open(path3) 45 46 rows = range(xrows) 47 rows.reverse() 48 for y in rows: 49 box = (x*tilesizeTo[0],y*tilesizeTo[1],(x+1)*tilesizeTo[0],(y+1)*tilesizeTo[1]) 50 #print box 51 newimg = img.crop(box) 52 y = int(name)*xrows + xrows - y -1 53 print x,y 54 path2 = "%s/%s/%02d/000/000/%02d/000/000/%02d.png"%(destDir,layerName,scale,newcol,y) #注意產(chǎn)生的文件編號(hào)的數(shù)值寬度 55 newimg.save(path2) 56 57 def test(*a,**b): 58 print len(a),b 59 #test(1,2,3,k=100) 60 61 if __name__=='__main__': 62 splitTile('layer1',1,'E:/NewGis/trunk/python/tile1','E:/NewGis/trunk/python/tile2',(512,512),(32,32))
1 # -*- coding:utf-8 -*- 2 3 #計(jì)算的網(wǎng)格數(shù)量 4 5 import sys, traceback,threading,time,struct,os,os.path,shutil,distutils.dir_util,array,base64,zlib 6 7 DPI= 90.0 #每英寸的像素?cái)?shù)量 8 METRER_PER_INCH = 2.54 /100.0 #每英寸多少米 9 PIXEL_WIDTH = METRER_PER_INCH / DPI #每個(gè)象素多少米 10 11 METERS_PER_DEGREE = 1862 * 60 12 13 SCALE = 100000 #縮放比 14 15 GEO_RECT = (70,10,134,60) 16 17 w = (GEO_RECT[2]-GEO_RECT[0]) * METERS_PER_DEGREE 18 h = (GEO_RECT[3]-GEO_RECT[1]) * METERS_PER_DEGREE 19 20 TILE_WIDTH = 1024*4 #圖塊規(guī)格 21 TILE_HEIGHT = TILE_WIDTH 22 RENDER_TILE_TIME = 1 23 24 25 ynum = h / (TILE_HEIGHT*PIXEL_WIDTH*SCALE) # SCALE 縮放比例下tile規(guī)格的數(shù)量 26 xnum = w /(TILE_WIDTH*PIXEL_WIDTH*SCALE) # tile的列數(shù)量 27 print "scale:%s,tiles(%s,%s)"%(SCALE,int(xnum),int(ynum)) 28 print u"總圖塊數(shù)量:",xnum*ynum,u"消耗時(shí)長(zhǎng)",xnum*ynum*RENDER_TILE_TIME/3600.0,u"小時(shí)(每圖塊耗時(shí)%s秒)"%RENDER_TILE_TIME 29 30 #----------------------------------------- 31 RESOLUTION = 0.000018 #顯示精度 每像素多少度 32 #RESOLUTION = 0.0003 #顯示精度 每像素多少度 33 SCALE = RESOLUTION * METERS_PER_DEGREE / PIXEL_WIDTH #計(jì)算顯示比例 34 ynum = h / (TILE_HEIGHT*PIXEL_WIDTH*SCALE) # SCALE 縮放比例下tile規(guī)格的數(shù)量 35 xnum = w /(TILE_WIDTH*PIXEL_WIDTH*SCALE) # tile的列數(shù)量 36 ynum = int(ynum) 37 xnum = int(xnum) 38 print xnum,ynum, TILE_WIDTH*PIXEL_WIDTH*SCALE 39 print str(RESOLUTION),"scale:%s,tiles(%s,%s)"%(SCALE,int(xnum),int(ynum)) 40 41 print u"總圖塊數(shù)量:",xnum*ynum,u"消耗時(shí)長(zhǎng)",xnum*ynum*RENDER_TILE_TIME/3600.0,u"小時(shí)(每圖塊耗時(shí)%s秒)"%RENDER_TILE_TIME 42
估計(jì)不是這次的事情,再過(guò)4,5年也不一定會(huì)去東北,而且是行色匆匆 昨天與老陳約好去ying信調(diào)測(cè)酒店代理度服務(wù)器的事情,老陳就是老陳,擺弄了幾下就在一臺(tái)linux主機(jī)上配置完了iptables,來(lái)不及跟這一幫子人過(guò)多的調(diào)侃閑聊了,老姐又激動(dòng)的幾乎暈過(guò)去,告知園園現(xiàn)在到了哈爾濱。 馬上與老陳告別,交代了一下httpproxy代碼的安裝和運(yùn)行便開(kāi)車(chē)去見(jiàn)老姐,帶其到三林之后取了1w塊現(xiàn)金便開(kāi)車(chē)直接去了浦東機(jī)場(chǎng) 3點(diǎn)半的飛機(jī),1900塊的價(jià)格讓我乍舌了一下,沒(méi)有打折的,沒(méi)法子了 說(shuō)實(shí)在的,提到飛機(jī)是有點(diǎn)發(fā)怵的,以前就做過(guò)3,4次,每次都跟自己說(shuō)以后再也不坐飛機(jī)了,大概是怕死,死了很多都白費(fèi)了 飛了近3小時(shí)到達(dá)哈爾濱,下飛機(jī)趕緊找個(gè)廁所尿了一下,知道園已經(jīng)在火車(chē)站附近的派出所已呆了白天了,比較著急,打了車(chē)便走,東北人也不地道,被宰了7,80塊 終于到了哈爾濱火車(chē)站,看到了牌子以及下面的大鬧鐘,還真的是哈爾濱,沿途看到了東北的殺豬菜xx飯店之類(lèi)的東北特色的名詞。 -12度,其實(shí)除了臉凍的發(fā)紫之外人整個(gè)都算還好,不是太冷,就是剛下過(guò)大雪所以地很滑。 東北確實(shí)破破爛爛的,最有特色的就是地上能很明顯看出行人吐的痰,一顆一顆的,星羅棋布,因?yàn)闅鉁氐退择R上結(jié)凍了,似乎細(xì)菌也被困所在了里面,所以顯得城市都很干凈。 一路找啊找,沒(méi)找到,又打了2,3個(gè)電話給園,東北人這個(gè)講話的口音還真是有問(wèn)題,含含糊糊的,一路打聽(tīng)到了那個(gè)站前車(chē)站派出所 推門(mén)進(jìn)去,眼睛被迷糊了,里面都很人,所以人說(shuō)東北外冷內(nèi)熱呢 園就在那里,看到我笑了笑,我也嚴(yán)肅很多,趕忙跟警察打招呼,表示感謝啊,一位馬警官給園買(mǎi)了吃的,我是非常的感激萬(wàn)分道謝,辦完手續(xù)之后便帶園出來(lái)吃了李先生,花了41塊錢(qián)。 出
來(lái)我問(wèn)園是否要買(mǎi)點(diǎn)啥,帶她去小店買(mǎi)點(diǎn)啥,想來(lái)想去還是買(mǎi)了條200的煙,出來(lái)找了路上一個(gè)小旅店拉客的小妹妹,塞了10塊錢(qián)讓她幫著把煙替我送給那個(gè)民
警,看她跑進(jìn)去了我便跟園走了,沒(méi)想到?jīng)]過(guò)一會(huì)兒那小妹妹追了我好長(zhǎng)一段,告訴我送到了,讓我放心,我拍了拍她一下肩膀,謝謝!東北人真好 一路找
住宿的地方,一時(shí)間看花了眼,正好碰上一位旅店拉客的東北大姐,高個(gè)子,長(zhǎng)得還不錯(cuò),應(yīng)該長(zhǎng)我4,5歲的樣子,本想著等一下去火車(chē)站買(mǎi)張晚上的車(chē)票趁著功
夫找家落腳的地方歇息一下便跟著大姐穿走在火車(chē)站附近街道,到了才發(fā)現(xiàn)是公房改建的小旅店,野路子旅店,看看這位大姐的熱情程度,算了就不打擊她了,暫時(shí)
付了30算到晚上12點(diǎn)之前的費(fèi)用。 園除了校服之外里面就直接是短褲和短袖T shirt了,真是胖子不怕挨凍,也是自作自受。 跟旅店大姐聊了一番,她從家翻出見(jiàn)滑雪服以50塊賣(mài)給了我,給這個(gè)園胖子穿上才好受了許多。還是挺劃算的,對(duì)這個(gè)東北大姐也多了一絲好感,畢竟東北人還是比較豪爽。 之
后我想去火車(chē)站,想想單獨(dú)留下園在這里也是不放心,便鎖了門(mén)帶上她一同出門(mén)?;疖?chē)站人可是真多,想買(mǎi)直達(dá)上海的車(chē)票還真是不簡(jiǎn)單,找半天來(lái)售票處都沒(méi)找
到,想想還是算了,打了了114查詢買(mǎi)明日的飛機(jī)票,電話里我頂了2張牌票子,5折,算下來(lái)1000一張,那還好,搞定了準(zhǔn)備帶園回去,一路上看看哈爾濱
的夜景,別的沒(méi)注意啥,就看到哈爾濱最出名的就是哈爾濱紅腸,哈哈,想著回去買(mǎi)一些。 晚上園胖子便呼呼大睡起來(lái),我也死活睡不過(guò)去,生物鐘還沒(méi)到呢。晚上請(qǐng)了個(gè)假,也被楊新笑話了一番。 早上8點(diǎn)半賣(mài)票處便電話過(guò)來(lái)與我確定送票地點(diǎn),發(fā)現(xiàn)她們漏定了1張,我便告知還有個(gè)14歲的兒童,事情麻煩了,沒(méi)法買(mǎi)票了,也打亂我今天原本的計(jì)劃了。 之后便電話給機(jī)場(chǎng)公安,機(jī)場(chǎng)安檢咨詢辦理手續(xù),其告知必須出具戶口本或者戶籍信息包括照片。想想昨天那煙送的還真是該,多做好事沒(méi)錯(cuò)吧! 園
胖子呼呼大睡,我便馬上起來(lái)又來(lái)到了站前治安大隊(duì),一個(gè)叫宮克的警察很吊,從我見(jiàn)他到離開(kāi),他一直在玩他的手機(jī),不知是不是在看色情信息這么投入,東北人
嘛講話就是這么含糊,我反映了情況之后希望他們能開(kāi)具相關(guān)證明,還算可以他們?cè)敢鈳兔?,也許是昨天煙的緣故,也許確實(shí)他們比較通事理,都是幾個(gè)50開(kāi)外的
老警察,總的還都算不錯(cuò)。最后是一位叫 陳正欽
的警官替我查了公安網(wǎng)內(nèi)的關(guān)于園的戶籍信息,單就是沒(méi)有照片,這個(gè)咋辦呢,一陣的范暈,一個(gè)勁的求再查查其他系統(tǒng),都沒(méi)有全的信息,機(jī)場(chǎng)公安又強(qiáng)調(diào)必須要
有照片。 在陳警官的指導(dǎo)下,讓我去附近的松花江派出所查詢小孩的戶籍信息,因?yàn)槲抑缊@拍過(guò)社???,有照片信息存儲(chǔ)的,所以便出來(lái)一路找到了派出所。 到
了這里,這里的民警一副很強(qiáng)橫的態(tài)度,要不是老子求他們辦事才不會(huì)裝得低三下四,哀求了多次,又找這里的領(lǐng)導(dǎo),被直接一口拒絕,說(shuō)是只對(duì)轄區(qū)人口負(fù)責(zé),其
他的他們沒(méi)有這個(gè)能力,簡(jiǎn)直是畜生,還是人民警察呢,就是這么為全國(guó)人民服務(wù)的啊,媽的!去了2次,求了n次,只好沒(méi)法,折回去的路上又給機(jī)場(chǎng)安檢尋求幫
助,安檢讓我拍照然后讓公安蓋章也行,想想那幫松花江的混蛋警察那里也不去了,直接去站前派出所找到陳警官咨詢,被告知可以,便開(kāi)心了起來(lái),道謝了一下,
趕緊跑回小旅店把園叫起來(lái),喂了點(diǎn)吃的給她,路上刻意留心過(guò)附近的照相館,所以拖著園一路小跑到了照相館,拍照,20元。 拿著照片再去站前派出所,陳警官外出了,等了20分鐘,他還是那么熱情,順利的辦完了證明,我可是千恩萬(wàn)謝,要沒(méi)有這個(gè)證明估計(jì)做火車(chē)要2天之后了。 出了大門(mén),再去李先生吃飯,點(diǎn)了幾個(gè)菜,吃了60多,席間我跟服務(wù)員要調(diào)羹,居然東北小妹沒(méi)聽(tīng)懂,惹得旁桌的客人都笑了。出來(lái)讓園胖子背對(duì)火車(chē)站給她留了個(gè)點(diǎn),呵呵! 看看時(shí)間10點(diǎn)半了,趕緊打車(chē)到民航大廈,11點(diǎn)的大巴一個(gè)小時(shí)到了太平機(jī)場(chǎng),路上大雪蓋地,這個(gè)鬼地方還是人口稀少,都是莊稼地,現(xiàn)在的東北農(nóng)民估計(jì)只好在家玩玩骰子了吧,整個(gè)大地都被凍起來(lái)了,一個(gè)勁的把這些村莊景象往鄉(xiāng)村愛(ài)情里的場(chǎng)景套。 到了機(jī)場(chǎng)買(mǎi)機(jī)票,出具了園的證明,還一直擔(dān)心著有啥問(wèn)題呢,給了錢(qián)拿了票,一下子放心了。在侯機(jī)的時(shí)候才想起東北香腸,這個(gè)機(jī)場(chǎng)還真是黑的厲害,2斤賣(mài)了80塊,想想算了,好歹也是來(lái)一次,也算給東北人民捐助了。 飛機(jī)延誤了1小時(shí)2點(diǎn)30正式開(kāi)飛。 東北常年陽(yáng)光明媚,所以干燥。到上海已經(jīng)5點(diǎn)30了,下著密雨,出了航站,找到自己的車(chē),出庫(kù),交停車(chē)費(fèi),100,真是吃人,也沒(méi)辦法,開(kāi)上radio,一路跟園時(shí)不時(shí)的聊上一兩句,顛簸著回家,把園交到了姐手里。
緣于要做個(gè)http代理服務(wù)器的需求,開(kāi)始琢磨SocketServer類(lèi),看看其有多優(yōu)秀 BaseServer: 定義基礎(chǔ)服務(wù)器接口,這些功能接口提供給子類(lèi)繼承。同時(shí)提供服務(wù)處理的骨架 serve_forever() 循環(huán)調(diào)用 handle_request() handle_request() 調(diào)用子類(lèi)的get_request() ,在tcpServer時(shí)實(shí)則進(jìn)行accept()應(yīng)答; 驗(yàn)證處理 verify_request(); 最終處理請(qǐng)求 process_request(), verify_request() 虛函數(shù) process_request() 虛函數(shù),這個(gè)函數(shù)并沒(méi)有直接在BaseServer的子類(lèi)TcpServer中被重載,而是在TcpServer的派生類(lèi)中通過(guò)另一個(gè)父類(lèi)來(lái)實(shí) 現(xiàn),比如 ThreadingTCPServer的基類(lèi)ThreadingMixIn.process_request()實(shí)現(xiàn)了此功能函數(shù) finish_request(request, client_address) 執(zhí)行一次完整的socket數(shù)據(jù)讀入處理,如果是ThreadMixInTcpServer產(chǎn)生的request,這個(gè)方法內(nèi)必須實(shí)行循環(huán)讀取socket數(shù)據(jù),直到socket關(guān)閉。(此處 request 就是 socket對(duì)象)
def finish_request(self, request, client_address): """Finish one request by instantiating RequestHandlerClass.""" self.RequestHandlerClass(request, client_address, self)
在finish_request里面便將讀取socket數(shù)據(jù)的任務(wù)扔給了RequestHandler去處理了,代碼可以跳過(guò)去看了 ##--------------------------------------------- TcpServer: tcp服務(wù)器 __init__(self, server_address, RequestHandlerClass) 需要提供服務(wù)偵聽(tīng)地址和請(qǐng)求處理類(lèi)對(duì)象 server_bind() 綁定服務(wù)器地址 server_activate() 激活服務(wù)器 server_close() 關(guān)閉服務(wù)器 fileno() 返回服務(wù)器socket的句柄fd編號(hào) get_request() 接收應(yīng)答accept() close_request(request) 關(guān)閉socket,request即為socket對(duì)象 三種輸出處理方式: 阻塞方式、線程處理(ThreadingMixIn)、進(jìn)程處理(ForkingMixIn) ThreadingMixIn: 線程模型 process_request( request, client_address) 為請(qǐng)求的鏈接創(chuàng)建新的線程,在創(chuàng)建線程時(shí)直接指定線程入口和參數(shù):
import threading t = threading.Thread(target = self.process_request_thread, args = (request, client_address)) if self.daemon_threads: t.setDaemon (1)
process_request_thread() 線程處理socket入口,負(fù)責(zé)接收數(shù)據(jù),代碼實(shí)現(xiàn)有點(diǎn)繞,看看代碼
def process_request_thread(self, request, client_address): try: self.finish_request(request, client_address) self.close_request(request) except: self.handle_error(request, client_address) self.close_request(request)
ThreadingMixIn 其實(shí)就是線程代理,還是調(diào)用finish_request()進(jìn)入處理tcp數(shù)據(jù)的循環(huán),處理完成便close_request()。但是finish_request和close_request并未在ThreadingMinxIn內(nèi)定義,在哪里呢? 通過(guò)研讀ThreadingTcpServer,原來(lái)通過(guò)ThreadingTcpServer這個(gè)finish_request又跑回了BaseServer.finish_request() ThreadingTCPServer(ThreadingMixIn, TCPServer) 裝配成線程池處理的tcp服務(wù)器 BaseRequestHandler: 請(qǐng)求處理基礎(chǔ)對(duì)象,提供統(tǒng)一的行為接口實(shí)現(xiàn)處理socket數(shù)據(jù)。 BaseRequestHandler比較好玩,在構(gòu)造函數(shù)內(nèi)完成了所有的操作,見(jiàn)代碼:
def __init__(self, request, client_address, server): self.request = request self.client_address = client_address self.server = server try: self.setup() self.handle() self.finish() finally: sys.exc_traceback = None # Help garbage collection
setup()對(duì)應(yīng)的子類(lèi)會(huì)進(jìn)行初始化處理 self.handle() 直接調(diào)用子類(lèi)的處理函數(shù),可以參考 BaseHTTPRequestHandler(SocketServer.StreamRequestHandler)::handle() StreamRequestHandler(BaseRequestHandler) 流式socket處理類(lèi) setup() 設(shè)置好socket對(duì)象和讀寫(xiě)文件句柄 rfile/wfile HTTPServer(SocketServer.TCPServer) http服務(wù)器 BaseHTTPRequestHandler(SocketServer.StreamRequestHandler) 流式的請(qǐng)求處理類(lèi) handle() 處理入口,在基類(lèi)BaseRequestHandle()的構(gòu)造函數(shù)中直接調(diào)用 handle_one_request() 如果不是處理一次則返回false。接收一次socket數(shù)據(jù),解析parse_request(),調(diào)用對(duì)應(yīng)的do_xxx事件 python 的daemon線程: 如果一個(gè)進(jìn)程的主線程運(yùn)行完畢而子線程還在執(zhí)行的話,那么進(jìn)程就不會(huì)退出,直到所有子線程結(jié)束為止,如何讓主線程結(jié)束的時(shí)候其他子線程也乖乖的跟老大撤退呢?那就要把那些不聽(tīng)話的人設(shè)置為聽(tīng)話的小弟,使用線程對(duì)象的setDaemon()方法,參數(shù)為bool型。True的話就代表你要聽(tīng)話,我老大(主線程)扯呼,你也要跟著撤,不能拖后腿。如果是False的話就不用那么聽(tīng)話了,老大允許你們將在外軍命有所不受的。需要注意的是setDaemon()方法必須在線程對(duì)象沒(méi)有調(diào)用start()方法之前調(diào)用,否則沒(méi)效果。
|