[精讚] [會員登入]
625

【Socket】(Linux / Python 3)兩不同系統的主機之間如何使用Socket相互溝通

How to connect two different computer use Socket

分享此文連結 //n.sfs.tw/15888

分享連結 【Socket】(Linux / Python 3)兩不同系統的主機之間如何使用Socket相互溝通@小編過路君子
(文章歡迎轉載,務必尊重版權註明連結來源)
2022-07-03 02:40:46 最後編修
2022-07-03 00:33:45 By 過路君子
 

大家好這裡是費了很多神的小編過路君子

趁著設備換新,一咬牙把一年半前的程式整個大改,改成小編看起來比較舒服的形式。

 

 

在約一年半之前,小編大約是使用 java 直接去呼叫 Linux 的 system call,換句話說基本上就是整套程式裸奔在系統內,整體的遷移性非常差。

轉眼間就過了一年半,原本的伺服器被更新、更強的伺服器取代了,而小編也主動將這兩支程式切開在不同的主機上,意思就是原本的方法不可以使用了。

那不瞞各位,一年半前也正是小編剛開始學習 Linux,對整套 Linux 怎麼運行還非常生疏,想想當初小編自己想出 syscall 的方式時還沾沾自喜,現在回頭去看,這到底是什麼爛方法!

 

那這邊就簡單的用一張規格表來開場吧:

程式語言 作業系統 角色
Python3 Ubuntu 客戶端
Shell CentOS 7.9.2009 伺服器端

 

Shell

我們先來看看 Shell 這邊該如何啟動一個 socket。

那我們是使用 nc 這個套件來啟動 socket,而 nc 套件在 CentOS 7 的最小安裝下是沒有的,所以如果伺服器內沒有 nc 可以先下:

sudo yum install -y nc

 

然後就可以開始構築我們的 Linux shell 程式碼了。

既然 Shell 作為我們的伺服器端,那勢必得接受來自外部或是內部的連線請求,故相關的 IP 以及防火牆的設定需要另外去調整。

如果防火牆是使用 firewall,那防火牆設定指令可以參考小編這篇:【CentOS 8】 防火牆基本操作@小編過路君子

# 持續監聽埠
while true
do
    socketPID=""
    # 啟動 socket 並將其放到背景執行
    # 並且會在 50000 埠持續 listening
    # 使用 TCP 來連線
    # 若要使用 UDP 只需要加上 -u 即可
    coproc SOCKET { nc -l 0.0.0.0 50000; }

    # 開始讀取 socket 收到的訊息
    # 要回覆客戶端,只需要將訊息放入 echo 即可
    while read cmd
    do
        if [ "${cmd}" = "stop" ]; then
            echo "DONE"
            break
        elif [ "${cmd}" = "hello" ]; then
            echo "world"
        else
            echo "none"
        fi
    done <&"${SOCKET[0]}" >&"${SOCKET[1]}"

    # 殺掉此 socket
    # 避免埠被占用造成再次啟動失敗
    kill "${socketPID}"
done

那至於為什麼使用 echo 就可以將訊息回覆給客戶端,其實跟 coproc 和 ${SOCKET} 有關,這邊小編就不展開來講了。

相關概念為 Linux 的 pipe 指令和 Linux coproc 指令,有興趣的人可以自行搜尋相關資料。

 

Python3

由於 python3 作為客戶端,只要能跟我們的伺服器取得連線即可,防火牆或 IP 隨便。

不同於 shell,Python3 本身就已經內建了 socket 操作相關的函數,我們只需要直接 import 進來即可。

from socket import socket, AF_INET, SOCK_STREAM

class inServer():
    def connect(self):
        # 創建 socket 並使用 TCP 來連線
        console = socket(AF_INET, SOCK_STREAM)
        # 連線到遠端伺服器
        console.connect(("REMOTE_SERVER_IP", 5000))
        # 發送訊息到遠端伺服器
        console.send("hello\n".encode("utf-8"))

        # 等待伺服器回覆並解析該訊息
        msg = console.recv(1024).decode("utf-8")
        if msg == "world\n":
            console.send("stop\n".encode("utf-8"))
            # 關閉 socket
            console.close()

client = inServer()
client.connect()

 

大致上就這樣,非常簡單的連線範例,那其中最令人討厭的就是 \n,各位可以仔細觀察 Python3 發送的字串,以及 Shell 實際比對的字串,反之亦然。

基本上這是小編慢慢的經過好幾個小時一次又一次的測試,才終於抓出他們傳送以及比對字串的邏輯。

 

 

 

後記

本來小編一開始打算使用 web server 來撰寫此功能,但是後來想了想,沒必要為了幾個字串就使用 web server 這麼強大的功能,所以後來又轉向 net。

同樣的理由,所以最後選擇使用更底層的 socket 來傳遞訊息就好,這樣連 header 都省了,但是還是可以保持訊息的正確性。

END

你可能感興趣的文章

【!@#$%^&*()_+ language】!@#$%^&*()_+ 程式語言介紹 一款看起來像是在鬧的程式語言

【Javascript】(Event)常用的網頁事件 不寫下來絕對下又會忘記,然後每次又都要回到MDN去查,麻煩

【教程】(進階版)如何用Sigil製作一本高質量的epub 下載好了Sigil之後除了直接把文字貼進去以外,還有:變更字型、著色、導入CSS……等等功能,不知道你有沒有發現呢?

【MEGAcmd】[Linux] 如何解決Unable to connect to service: error=2 用了好久的軟體突然停止一切的運作了。

【Vim】解決貼上文字時出現過多空格的問題 換了新系統,有時候就算重裝軟體並且複製了設定檔也還是會出現非常奇怪的現象

【Wicket】[URI]使用Java取得目前網址 這是個還滿常用的功能,可惜 Wicket 沒有內建函式可以快速取得我們要的部分,只能依靠我們自己後期的字串剖析

我有話要說

>>

限制:留言最高字數1000字。 限制:未登入訪客,每則留言間隔需超過10分鐘,每日最多5則留言。

訪客留言

[無留言]

隨機好文

高捷少女:地下城的探險少女① 婕兒心中一奇,便走上前看著仔細。那塊凹進去的地方中心大約三公分厚,越往邊緣就越淺,圓型直徑十五公分。婕兒拿出銅盤對比一下,發現兩者大小竟然一致,銅盤似乎能夠完整的嵌進去。     婕兒看著凹槽,心中

高捷少女:美麗島的守護者(終) 「我是她的師娘,妳一定就是艾米莉亞吧?小雅昨晚有跟我說到您。」「師娘?」艾米疑惑不解。

艾米莉亞和高捷戀旅3① 「既然艾米莉亞小姐也來了,就把那個拿出來吧。」美麗島捷運商店的負責人說完,一名工作人員推著一個大箱子進入辦公室。他將箱子打開,將裡面的東西抬出來。艾米張大嘴巴

【日翻中歌詞】ピースサイン(Peace Sign) 那一天從我們的頭頂 輕掠而過的那架飛機 有點不可思議 還記得 為何呢?毫無意義 

【歌評】蓮台野夜行 - 少女秘封倶楽部 少女秘封俱樂部 我們的主角終於出場啦!這首歌一反蓮台野夜行的固有風格,總是華麗的開始又華麗的結束!