這裡不是指 Django
與 Flask
是 Python
本身的 Socket
套件。
但我有用過 Nginx
+ uwsgi
or gunicorn
+ Django
or Flask
過。
今天因為要改用 Socket
傳資料,只要最初連線一次後,就能一直雙通傳資料比較快。
但是網路管理員不願意開除了 80 Port
以外的 Port
給我,希望我將 Socket
跟 Nginx
搭起來。
但是我完全不知道怎麼搭??
例如 Django
有 wsgi.py
, Flask
有 app = Flask(__name__)
,之後用 uwsgi
或 gunicorn
串接起來就好了。
那 Socket
怎麼串?
我 Google
了很多 Python Socket + Nginx
都是 Django
與 Flask
的相關資訊。
求人給個參考文章參考...
簡單來講就是
Nginx
-> 80port
我的 Socket Server
-> Host: 192.168.x.xxx
, Port:9000
client(80 Port)
-> Nginx(80port)
-> Socket(9000port)
-> Nginx(80port)
-> client(80 Port)
。
客戶端Form POST ←→ NGINX ←→ PHP ←→ EXEC PYTHON
從頭到尾只要80或443,不需要任何socket,PHP用EXEC調用PYTHON,PYTHON以print(json)回傳值給PHP的調用,PHP再把接收到的回傳值回應給客戶
我前陣子有提到的幾個作品都用到這個作法,而都不用socket
<?php
if (isset($_POST["action"])) {
$action = $_POST["action"];
$value = $_POST["data"];
if ($action === "POSTPYTHON") {
echo exec("/usr/bin/python3 /home/userxxx/gggg.py '".$value."'");
die();
exit();
}
}
?>
至於python那裡你只要做print()回傳執行結果就好,exec()會處理接收
客戶端你只要能用一般的webclient/httprequest getstring by post就能搞定,所以建議用共通格式json來傳遞
我寫php用到python的原因,就是python可以調用selenium抓別人的網頁的資料,達到即時爬蟲又不用煩惱被"我不是機器人"擋下
如果是WEB Service base on Windows的環境做這種方法,會有亂碼的的問題,在客戶端做encode/decodeuri可解決這個問題
我沒有要開網頁傳送資料,後端與後端兩個不同地方傳送資料。
那就不用nginx,你直接用python開socket監聽80端口
如果你要使用python的機器上已有nginx且有在正常工作,那你無法再用python去監聽80,會報端口已被佔用鍞定的錯誤,除非你有辦法把nginx移除(呃!)不然應該無解
我回應的例子就是因為公司不允許任意開防火牆端口(映射、對應虛擬伺服器)使用,也不能任意開新電腦拿實體IP,可用的主機上都有各式各樣的伺服軟體在跑不能隨便移除,我只能用webapi(php) + python的方法來折中,跟有沒有要架網站無關,老板不開這個門,我就開另一扇窗而已
解決問題不只可以用【正統、正宗、名門正派】的方法去解決,有時旁門左道,會更好用!
哦!我的Nginx80 port 是要給架設 Django 的網站用的不能移除,但要在一個機器上 run DjangoServer 以及 SocketServer 。
django 裡弄個特殊的頁面跑你的python,不行嗎?
可是我沒有要用網頁傳送資料,是外部的後端連到Server後端傳送資料。
咳............有誰跟你說WebAPI/Service就是做給人看的網頁?很多人(我也會)寫程式也會用IIS/Apache/nginx 上建一個WebAPI,用httprequests來傳遞資料,不用為了傳資料,要費心學學Socket還要另外在防火牆上開映射或多綁一個IP
這個是我放在公司在外面工地工務所裡的樹莓派裡的python程式,主要的工作就是把工地的指紋機裡的出勤記錄,定時從機器上下載,打包後POST總公司網站IIS裡的WebAPI
def addenroll(attlog, mid):
url = "http://erp.XXXXXXXX.com.tw/addenroll.aspx"
if isinstance(attlog, list):
#開始回存記錄到伺服器
loglist = list()
logpost = "["
vlen = len(attlog)
for l in range(vlen):
log = attlog[l]
xd = log[2]
logitem = '"{0},{1},{2},{3},1,{4},0,{5}"'.format(xd.strftime(
"%Y,%m,%d"), xd.strftime("%H,%M,%S"), str(1000+mid), log[0], log[1], mid)
logpost += logitem
loglist.append(logitem)
if l < (vlen-1):
logpost += ","
logpost += "]"
resp = requests.post(url, data={"PostEnrollRecords": logpost})
return
# ZK就是我家的指紋機,自己寫的class處理設備連接驅動
mid = 55
#55是設備編號,每台都有一個唯一的編號,存進資料庫後,我才知道是誰按了哪一個工務所的指紋機啊~~
zk.connect()
if zk.isconnect:
attlogs = zk.getAttendance()
if attlogs != False:
addenroll(attlogs, mid)
zk.disconnect()
例子裡的 addenroll.aspx 就是我講的 WebAPI ..
處理的事也很簡單,把Client端(樹莓派)post來的資料,解構json後回存資料庫
好的!我知道了!我研究 WebSocket 怎麼寫 Server 與 Client !
websocket應該比較適合你。
下面這是yarn run dev起來,測試伺服器用來做hot reload的websocket設定,你可以參考看看。
基本上就是websocket會走/sockjs-node這條路由,然後導向後端server的ip和port。
location /sockjs-node {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://localhost:8080;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
我現在不會寫 Web-Socket,沒有範例的 server.py與 client.py,現階段我只能用 純 Socket寫 ,並且我沒有要開網頁傳資料,都是後端與後端傳送資料。
我不清楚 sockjs-node 是怎麼出來的,我只能用 Python 寫。
你還是詳細敘述你到底要幹麻?
你要在網頁上傳資料?要像網頁聊天軟體一樣?還是要透過 internet 傳socket控制機器(是的話我也只能說你很大膽)?
在網頁上的即時應用,我建議你去查websocket。
要透過網頁控制機器,可以像下面japhenchen大的方法去做。
我沒有要在網頁上傳資料,是要通過外部的 Client 透過 internet 傳到 ServerSocket 接著 Server Socket 回傳資料給 Client。
你敢在網際網路傳socket...我真的只能說你很大膽。
依你的使用狀況
這樣建議server做webapi傳json,client post資料給web server,然後傳回資料就好。
哦哦,看來不能用 socket 傳送資料只能學 ServerSocket 了!