1. 程式人生 > >Python 實現程序間通訊(網路程式設計)

Python 實現程序間通訊(網路程式設計)

網路程式設計

  1):網路程式設計是什麼意思,網路程式設計指的是不同機器之間通過網編相互發資訊,我們常用的“QQ”,“微信”,“郵箱” 都個網編程式設計的應用;

  網編程式設計在技術上還有另一個叫法叫“程序間通訊”,程序間通訊這個名字能更好體現技術的內涵,說白了就是一個程序給另一個程序發

  資訊;

  2):網路程式設計中的兩個重要的角色,“服務端”,“客戶端” 從技術上來講“服務端”是被動的,它監聽在某個“套結字(socket)”上,被動的

  等待“客戶端”的連線;也就是說連線是由“客戶端”主動發起的,所以“客戶端”是主動的。

  3):主動&被動對應著兩套不同的行為,對於被動的“服務端”來說它有三個技術上的步驟要做 “第一步:bind

”,“第二步:listen”,“

  三步 accept” 這三步是基本的“套路”不要問我為什麼,我也想知道;不過總的來說前兩步叫“監聽”,第三步叫“接收一個客戶端連線

  對於“客戶端”它的套路就比較少了只有一步:“唯一一步:connect” 成功後就能與伺服器之間有進行資訊的收發了。

從最低層的socket來實現一個翻譯功能

  我在這要實現的“翻譯”功能比較“牛逼”,總的來說是這樣的;客戶端向伺服器傳送一串小寫字母,伺服器端把小寫“翻譯”成大寫後返回

  我的伺服器主機的IP是“172.16.192.100”

  1): 服務端程式碼

#! /usr/bin/env python3

import
socket

if __name__ == "__main__": #定義一個服務端的tcp套節字 with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s_sock: s_host = ('172.16.192.100',9999) s_sock.bind(s_host) # 第一步:bind s_sock.listen(5) # 第二步:listen print("服務端啟動完成 監聽在 {0}".format(s_host)) while
True: c_sock,c_addr = s_sock.accept() # 第三步:接收客戶端連線 print("收到來自 {0} 的連線請求".format(c_addr)) c_data = c_sock.recv(1024) # 讀取客戶端發來的資料 c_str = str(c_data,"utf-8") # 由位元組序列轉碼成utf-8字串 print("收到來自 {0} 的資訊 '{1}' ".format(c_addr,c_str)) c_sock.sendall( bytes(c_str.upper(),"utf-8")) # 翻譯成大寫傳送到客戶端

  2): 客戶端程式碼

import socket
from datetime import datetime


if __name__ == "__main__":
    data = ' '.join(sys.argv[1:])
    with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as sock:
        sock.connect(('172.16.192.100',9999))
        print("client {0} 傳送 {1}".format(datetime.now(),data))
        sock.sendall(bytes(data,"utf-8"))

        received_data = sock.recv(1024)
        print("client {0} 收到 {1}".format(datetime.now(),received_data))

  3): 服務端的執行情況

python3 server.py 
服務端啟動完成 監聽在 ('172.16.192.100', 9999)
收到來自 ('172.16.192.1', 52160) 的連線請求
收到來自 ('172.16.192.1', 52160) 的資訊 'Hello world 123'

  4): 客戶端的執行情況

python3 client.py Hello world 123
client 2018-09-19 16:42:46.973864 傳送 Hello world 123
client 2018-09-19 16:42:46.974519 收到 b'HELLO WORLD 123'

 【Python對網路程式設計做了什麼

  從上面的內容可以看出“服務端”是有它的固定套路的,Python把這些通用的“套路”抽象了來了,如果我們使用python寫上面的那種“服務端”

  &“客戶端”的程式的話就大的方便了。

  服務端直接這樣寫就行了:

import socketserver

class UpHander(socketserver.BaseRequestHandler):
    def handle(self):
        """
        self.request  引用的是與客戶端通訊用的socket物件
        """
        data = self.request.recv(1024) # 接收1024個位元組
        print("接收到來自 {0} 的資訊 {1}".format(self.client_address,str(data)))
        self.request.sendall(data.upper()) # 把接收到的資料變成大寫再發出去

if __name__ == "__main__":
    server_ip = ('172.16.192.100',9999) # 定義服務端監聽的ip與埠
    with socketserver.TCPServer(server_ip,UpHander) as server:
        server.serve_forever()

  通過“重寫”socketserver.BaseRequestHandler.handle 方法來實現我們要的功能,也就是說我們不要太在意網路程式設計的技術細節了;注意

  了上面的這個實現是“序列”的,也就是說server端只有一個程序來做處理,如果是要實現一個並行處理的服務端的話也是分分鐘的事

多執行緒版本的服務端程式設計

  1): 服務端程式碼

#! /usr/bin/env python3

"""
用python標準庫實現一個簡單的c/s架構的服務
"""

import socketserver
import socket
import time
import threading

class UpHander(socketserver.BaseRequestHandler):
    def handle(self):
        """
        self.request  引用的是與客戶端通訊用的socket物件
        """
        data = self.request.recv(1024) # 接收1024個位元組
        cur_thread = threading.current_thread()
        print("服務端執行緒號 {0} 接收到來自 {1} 的資訊 {2}".format(cur_thread.name,self.client_address,str(data)))
        time.sleep(5)
        self.request.sendall(data.upper()) # 把接收到的資料變成大寫再發出去


class MultiThreadTcpServer(socketserver.ThreadingMixIn,socketserver.TCPServer):
    pass

if __name__ == "__main__":
    with MultiThreadTcpServer(('172.16.192.100',9999),UpHander) as s_sock:
        s_thread = threading.Thread(target=s_sock.serve_forever)
        s_thread.daemon=True
        s_thread.start()
        print("多執行緒版本的服務端已經啟動...")
        while True:
            time.sleep(10) # 使服務端永不退出

  2): 客戶端程式碼

import socket
from datetime import datetime


if __name__ == "__main__":
    data = ' '.join(sys.argv[1:])
    with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as sock:
        sock.connect(('172.16.192.100',9999))
        print("client {0} 傳送 {1}".format(datetime.now(),data))
        sock.sendall(bytes(data,"utf-8"))

        received_data = sock.recv(1024)
        print("client {0} 收到 {1}".format(datetime.now(),received_data))

  開啟兩個客戶端觀察效果

1:
python3 client.py Hello world 123
client 2018-09-19 17:47:38.084209 傳送 Hello world 123
client 2018-09-19 17:47:43.091790 收到 b'HELLO WORLD 123'


2:

python3 client.py Hello world
client 2018-09-19 17:47:38.803440 傳送 Hello world
client 2018-09-19 17:47:43.811177 收到 b'HELLO WORLD'

  由時間上可以看出來請求是並行的

總結

  可以看出用socketserver模組來做“伺服器”,“客戶端”的程式設計是非常方便的

學習交流

 -----------------------------http://www.sqlpy.com-------------------------------------------------

-----------------------------http://www.sqlpy.com-------------------------------------------------

相關推薦

Python 實現程序通訊(網路程式設計)

【網路程式設計】   1):網路程式設計是什麼意思,網路程式設計指的是不同機器之間通過網編相互發資訊,我們常用的“QQ”,“微信”,“郵箱” 都個網編程式設計的應用;   網編程式設計在技術上還有另一個叫法叫“程序間通訊”,程序間通訊這個名字能更好體現技術的內涵,說白了就是一個程序給另一個程序發   資訊;

Windows核心程式設計之郵槽實現程序通訊

    郵槽是Windows系統提供的一種單向通訊的機制。即程序中的一方只能寫入或讀取資料,而另一方則只能讀取或寫入資料。通過郵槽,使用者可以實現一對多或跨網路的程序之間的通訊。但是,郵槽能傳輸的資料

Python socket 實現程序通訊

基本用法 Python socket 使用方法如下 socket = socket.socket(family, type[, protocal]) family代表地址家族,一般為AF_UN

python Queue模組實現程序通訊

Queue本身是一個訊息列隊程式,可以通過這個模組來進行程序之間的相互通訊[Python] syntaxhighlighter_viewsource syntaxhighlighter_copycode?010203040506070809101112131415161718

iOS--CFMessagePort實現程序通訊

CFMessagePort屬於CoreFoundation框架中的類。因此可以在http://opensource.apple.com/tarballs/CF/CF-855.17.tar.gz中在原始碼,如果感興趣可以去看看。 下面說下CFMessagePortRef的具體使用。 首先建立一

Android BroadcastReceiver使用,可實現程序通訊

1、建立廣播接收器: /** * 作者:created by meixi * 郵箱:[email protected] * 日期:2018/11/1 09 */ public class MyBroadcastReceiver extends BroadcastReceiver

C#使用SendMessage實現程序通訊的方法

本文例項講述了C#使用SendMessage實現程序間通訊的方法。分享給大家供大家參考。具體分析如下: 為了深入理解訊息機制,先來做一個測試專案 在新建專案的Form1的程式碼中,加入方法: ?

Android AIDL實現程序通訊

        今天犯二了, 犯了個超級低階的錯誤, 真的是丟人丟大發了.         剛好順道反思下, 也對工作這幾年做一些簡單的總結. 不知道你們是不是和我一樣也總遇到各

Linux 通過共享記憶體機制實現程序通訊

問題背景 編寫程式 sender ,它建立一個共享記憶體,然後等待使用者通過終端輸入一串字元,並將這串字元通過共享記憶體傳送給 receiver;最後,它等待 receiver 的應答,收到應答訊息後,將接收到的應答資訊顯示在終端螢幕上,刪除共享記憶體,結束程式的執行。 編寫 receiver 程

linux 用命名管道實現程序通訊

什麼是命名管道 命名管道和匿名管道一樣適用於程序之間的通訊linux匿名管道詳解,但是使用範圍不同,匿名管道要求必須是親緣程序,而命名管道卻沒有這個限制,它可以用於同一臺機器主機上的任意程序間通訊。

android Aidl 實現程序通訊

1​,android 新建aidl 檔案 刪除void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString);這個方法沒用到 還需要實

第18天Service-Messager實現程序通訊

第18天Service-Messager實現程序間通訊 Messager 一.Messager介紹 二.Messager的原理 特點: 三 .使用步驟 服務端moudle:messager

Java使用管道實現程序通訊

1.程序通訊 大家都知道程序間通訊有三種常用方式: 1)管道 2)共享記憶體 3)socket baidu也有說8種方式的,其實基本都是這三種方式的進一步細化。 2.Java程序通訊 Java沒有共享記憶體機制,同時Java的管道也只能用於Java執行緒間的通訊。 下

Linux程序通訊(IPC)程式設計實踐(十二)Posix訊息佇列--基本API的使用

posix訊息佇列與system v訊息佇列的差別: (1)對posix訊息佇列的讀總是返回最高優先順序的最早訊息,對system v訊息佇列的讀則可以返回任意指定優先順序的訊息。 (2)當往一個空佇列放置一個訊息時,posix訊息佇列允許產生一個訊號或啟動一個執行緒,

python程序通訊 訊息佇列

import multiprocessing import time #使用佇列,將訊息寫進佇列,需要的程序到佇列取 #佇列由父程序建立,子程序共享佇列 def write(qe): print("啟動子程序 write") for chr in ['A','B','C','D

Android Studio使用AIDL 實現程序通訊例項

參考:部落格:http://www.cnblogs.com/BeyondAnyTime/p/3204119.html, http://www.cnblogs.com/linlf03/p/3192025.html     視訊教程:http://www.imooc.com/l

Windows or Linux環境下利用“共享記憶體”實現程序通訊的C/C++程式碼

程序A對應的程式: #include <iostream> #include <windows.h> using namespace std; #define BUF_SIZE 1025 char szName[] = "NameOfMappi

Linux程序通訊(IPC)程式設計實踐(十)System V訊號量---PV操作經典題目

//P原語     //P(semaphore *S)     wait(semaphore *S)       {           -- S->value;           if (S->value < 0)           {   

訊號量與共享記憶體實現程序通訊(生產者消費者問題為例)

(一)訊號量訊號量是IPC的一種,可以看做是一個計數器,計數值為可用的共享資源的數量,訊號量可用於多程序的同步,為多個程序提供對共享資源的訪問。linux下的訊號量的介面函式如下:/*(1)獲取訊號量*/int semget(key_t key, int semnum, in

Linux訊息佇列實現程序通訊

什麼是訊息佇列: 訊息佇列提供了從一個程序向另一個程序傳送一個有型別資料塊的方法。用這種方法可以避免命名管道的同步和阻塞問題。訊息佇列是基於訊息的,而管道是基於位元組流的,並且訊息佇列的讀取不一定是先入先出。 訊息佇列的操作: 訊息佇列的建立或者獲取: int msgg