iT邦幫忙

0

Server端長時間未接收訊息,自己斷開連線。

大家好,這次想問關於Socket Server的問題。

基本架構如下,使用的是Websocket協議進行連接。
https://ithelp.ithome.com.tw/upload/images/20201124/20130097G37teybj5H.png

目前遇到的問題是:當長時間沒有傳送訊息時,Server端會斷開連結,並且輸入任何指令都毫無反應。

我測試過:間隔2分鐘傳送一次訊息,持續三天都沒有斷開連結。
https://ithelp.ithome.com.tw/upload/images/20201124/20130097Ro3BH2wv5w.png

還有間隔4分、5分、6分、8分都不會有這個問題。
但如果我拉長到15分、18分、20分,Server端就會失去連線。

目前在測試間隔12分鐘的狀態。
推測是,Server端超過一定時間未接收消息,Server端就會斷開連結。

這是我的Server端程式碼:

#coding=utf-8
import socket
import sys
import os
import datetime

HOST = 'IP'
PORT = Port

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))
server.listen(10)

print('Server start st %s:%s' % (HOST, PORT))
print('wait for connection...')

while True:    
    conn, addr = server.accept()
    print('connection by ' + str(addr))

    while True:
        clientMessage = str(conn.recv(1024), encoding = 'utf-8')#轉碼成utf-8
        if clientMessage.lower() == 'close':
            conn.close()
            print('client closed connection.')
            break
        print('recv:' + clientMessage)

        outdata = 'echo: ' +  clientMessage + '\n\r'
        conn.send(outdata.encode())

        '''這邊是我要記錄接收訊息的log'''
        theTime = datetime.datetime.now()
        message = str(theTime) + "  message:" +  clientMessage+'\n'
        f = open("data/log.txt","a")
        f.write(message)
        f.close

我原本在猜是不是Python的while迴圈有秒數限制,可是google過沒有這方面的答案。
我也想過,是不是Windows自己本身會把長時間沒有動作的程式給砍掉,但又不知道從何搜尋起。
想請問各位大大,有沒有什麼關鍵字可以讓我去搜尋的,謝謝!

1 個回答

3
japhenchen
iT邦大師 1 級 ‧ 2020-11-24 11:04:12
最佳解答

很多傳輸協定都會防止長時間佔用,或client端當機佔用連接,會做connection timeout,只要一段時間沒封包動作,就會由伺服器端直接中斷連線,像是http、ftp、ssh........這不奇怪,如果你想持續連接,請一段時間發送一組無意義的訊息noop給伺服端,讓他認為你還alive

還有某些防火牆也會封鎖及中斷長時間連線,這點你也要自己去查看看是否有此設定

但持續連接並不是一件好事,非必要最好是送完即斷,或是一段時間收集所有感測器的資訊記錄,打包壓縮送到伺服端,會比較不會浪費連接資源(不過這就要改伺服端的程式了)

看更多先前的回應...收起先前的回應...
雷伊 iT邦好手 1 級 ‧ 2020-11-24 11:12:13 檢舉

不愧是japhenchen
我就只能想到是用戶端休眠網卡喚醒後失聯

喔喔喔!原來是這樣!
那我的思路要改了。

謝謝大大解惑!(ノ>ω<)ノ

不好意思,再請問一下。

我是使用cmd.exe輸入python server.py來啟動伺服器的。
為何當Server端切斷連線時,我的Server會當機毫無反應,連Ctrl+C都沒辦法跳脫。

這突然讓我有點疑惑:
到底是Server先主動切斷連線,造成無法跳出While迴圈,所以才會當機。
還是Server自己當機了,所以才會中斷連線?

推測是崩潰當掉了。
一般來說,最好還是不要有如while的無限回圈。
就算要有,要需要非常了解其內的記憶體操作的相關知識。
你可以用你的資源管理器來查看你在運行時的cpu效能及記憶體的應用。
看看是不是一直持續增加。

如果會持續增加的情況。那早晚會因為系統保護的關係而導致崩潰運行。
一般從你的程式來看。那個開檔動作有可能是原兇之一。

以上只是單純的猜測。

我猜是被防火牆給阻擋長時間連線,而Server卻在苦苦等資料....掉進無限迴圈出不來,沒有做Timeout做中止跳出迴圈的條件吧.......

網路的狀況千奇百怪,千萬不要有"一定"會有回應的機制在,如果等不到超過N秒,就斷了吧

我也覺得是被防火牆擋住了。

嘗試把windows防火牆關閉試試看?

星空大:
剛剛試了一次,沒有發現效能需求持續增加的情況
有接收封包時,才有1%2%的增加。
感覺不太像是這邊的問題。

然後,為了確認能否主動跳脫while迴圈,所以我在保持連接的情況下,按下Ctrl+C卻沒辦法跳脫。
所以比較可能像是japhenchen大說的那樣:
連線被切斷→Server等待資料→我想停止Server按下Ctrl+C→結果Server沒反應→我以為Server掛了。

目前,我先使用定期傳送封包的方式來維持連線。
然後再找找看,python Server或是我在使用的4G Module是不是還有其他alive、timeout、Heartbeat之類的屬性可以設定。

總之,謝謝兩位的解答!


更新!

剛剛觀測到使用C語言架設的Server也會斷線,重複四次相同組態都是一樣的結果!
所以問題收縮了!可以確定不是防火牆,就是中華電信的問題了!

ifonly0216:
防火牆的設定,在我架設的那個port已經全部打開了。
如果要全部打開的話,等一下再來試試看。
但說實話,防火牆全開真的有點抖OwQ

一般我之前測試會先暫時關掉。測試完再開。
利用關閉的況下判斷是否可以正常。如果還是不正常至少可以先排除防火的問題。

不過因為我是測試機,可以這樣幹。
正式機這樣幹可能會被打死。

倒不是端口的問題,而是特殊控管,比如持續連接超過幾分鐘,或是單一IP的連接數過多,或是持續傳輸超過多少MB,就會中斷連線.......ShareTech的防火牆就有這群設定

星空大:
可能就先這樣子了吧(苦笑,再找機會問問主管這方面是否能測試一下,如果不行,我也就只能這樣子了,可能有機會再用自家的舊電腦玩玩看吧

japhenchen大:
了解!我再往這方面查詢看看!謝謝建議!

我要發表回答

立即登入回答