python 之 網絡編程(基於TCP協議的套接字通訊操做)

第八章網絡編程

8.1 基於TCP協議的套接字通訊

服務端套接字函數shell

s.bind()    綁定(主機,端口號)到套接字
s.listen()  開始TCP監聽
s.accept()  被動接受TCP客戶的鏈接,(阻塞式)等待鏈接的到來

客戶端套接字函數編程

s.connect()     主動初始化TCP服務器鏈接
s.connect_ex()  connect()函數的擴展版本,出錯時返回出錯碼,而不是拋出異常

公共用途的套接字函數windows

s.recv()            接收TCP數據
s.send()            發送TCP數據(send在待發送數據量大於己端緩存區剩餘空間時,數據丟失,不會發完)
s.sendall()         發送完整的TCP數據(本質就是循環調用send,sendall在待發送數據量大於己端緩存區剩餘空間時,數據不丟失,循環調用send直到發完)
s.recvfrom()        接收UDP數據
s.sendto()          發送UDP數據
s.getpeername()     鏈接到當前套接字的遠端的地址
s.getsockname()     當前套接字的地址
s.getsockopt()      返回指定套接字的參數
s.setsockopt()      設置指定套接字的參數
s.close()           關閉套接字

面向鎖的套接字方法緩存

s.setblocking()     設置套接字的阻塞與非阻塞模式
s.settimeout()      設置阻塞套接字操做的超時時間
s.gettimeout()      獲得阻塞套接字操做的超時時間

面向文件的套接字的函數服務器

s.fileno()          套接字的文件描述符
s.makefile()        建立一個與該套接字相關的文件

8.2 客戶端與服務端操做( 基於TCP )

tcp是基於連接的,必須先啓動服務端,而後再啓動客戶端去連接服務端網絡

socket是位於應用層與傳輸層之間的一個抽象層,專門把傳輸層如下的協議封裝成接口提供給應用層使用,應用只須要調用socket的接口或者說按照socket的標準編寫程序,寫出的程序天然是遵循TCP/IP協議socket

tcp的協議數據不會丟,沒有收完包,下次接收,會繼續上次繼續接收,己端老是在收到ack時纔會清除緩衝區內容。數據是可靠的,可是會粘包tcp

客戶端:函數

import socket
                  #地址家族,基於網絡    TCP協議
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)    # 建立客戶套接字
phone.connect(('127.0.0.1',8080))#服務端ip和端口    # 嘗試鏈接服務器
​
phone.send('你好'.encode('utf-8'))                       # 發消息b'hello'
data=phone.recv(1024)                                   #收消息
print(data.decode('utf-8'))
​
phone.close()                                          # 關閉客戶套接字

服務端:編碼

import socket
​
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 建立服務器套接字
phone.bind(('127.0.0.1',8080)                        #地址綁定到套接字(0-65535) 0-1024給系統用的
phone.listen(5)                                     # 監聽連接
print('start...')
conn,client_addr=phone.accept()         # 接受客戶端連接
print('鏈接來了:',conn,client_addr)     #conn: 鏈接對象   client_addr: 客戶端的ip和端口 
# 收發消息
msg=conn.recv(1024)                    #收消息,1024是一個最大的限制
print('客戶端的消息: ',msg)
conn.send(msg+b'SB')
​
# 掛電話
conn.close()    #關閉客戶端套接字
# 關機
phone.close()   #關閉服務器套接字(可選)

8.21 加上通訊循環與鏈接循環

服務端:

import socket
​
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8081))
phone.listen(5)
​
print('start...')
while True:                         # 鏈接循環
    conn,client_addr=phone.accept()
    print('客戶端 ',client_addr)
​
    while True:                      # 通訊循環
        try:
            msg=conn.recv(1024)
            print('客戶端的消息: ',msg)
            conn.send(msg+b'SB')
        except ConnectionResetError:   #只有在當前客戶端中止向服務端發送信息時,下一個客戶端才能發送
            break                   
    conn.close()
phone.close()

客戶端:

import socket
​
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 買電話
phone.connect(('127.0.0.1',8081)) # 嘗試鏈接服務器 地址爲服務端的ip和端口
while True:
    msg=input('>>>: ').strip()
    phone.send(msg.encode('utf-8')) # 發消息b'hello'
    data=phone.recv(1024) #收消息
    print(data.decode('utf-8'))
​
phone.close()

8.3 遠程執行命令的程序

注意:

res=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)

的結果的編碼是以當前所在的系統爲準的,若是是windows,那麼res.stdout.read()讀出的就是GBK編碼的,在接收端須要用GBK解碼,且只能從管道里讀一次結果

客戶端:

from socket import *
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
​
while True:
    cmd=input('>>>: ').strip()
    if not cmd:
        continue
    client.send(cmd.encode('utf-8'))
    res=client.recv(14744)
    print(res.decode('gbk'))#subprocess返回byte類型,須要gbk解碼
client.close()

服務端:

from socket import *
import subprocess
​
server=socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)
​
while True:
    conn,client_addr=server.accept() #(鏈接對象,客戶端的ip和端口)
    print(client_addr)
    while True:
        try:
            cmd=conn.recv(1024)
            obj=subprocess.Popen(cmd.decode('utf-8'),#subprocess返回byte類型,可直接傳輸但須要gbk解碼
                                 shell=True,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE
                                 )
            stdout=obj.stdout.read()
            stderr=obj.stderr.read()
        
            total=stdout + stderr# 發送真實的數據
            conn.send(total)
        except ConnectionResetError:
            break
    conn.close()
server.close()
相關文章
相關標籤/搜索