Python3:Socket通信(Socket模塊)


功能目的:通過socket的方式client發送"指令"獲取server端的文件,獲取文件結束後關閉client和server端的套接字

server端實現

from socket import *
import threading
import sys

HOST = ''
PORT = 12345
BUFSIZ = 1024
ADDR = (HOST, PORT)
sub_threads = []

# 創建套接字
server_sock = socket(AF_INET, SOCK_STREAM)

# 設定超時時間後,socket其實內部變成了非阻塞
server_sock.settimeout(5.0)

# 綁定地址(ip地址,端口)到套接字,參數必須是元組的格式
server_sock.bind(ADDR)

# 開始監聽,5爲最大掛起的連接數
server_sock.listen(5)


def handle(connected_sock):
    while True:
        data = connected_sock.recv(BUFSIZ)
        if not data:
            connected_sock.close()
            break
        # 傳輸文件
        if data == b'100':
            data = ''
            try:
                fd = open('../Files/sendFile1.txt', 'r')
                lines = fd.readlines()
                for line in lines:
                    data += line
                fd.close()
            except Exception:
                type, value, traceback = sys.exc_info()
                print('Exception: ', value)
            file_name = 'file_name:sendFile1.txt'.encode()
            send_data = data.encode()
            connected_sock.sendall(file_name)
            connected_sock.sendall(send_data)
            connected_sock.sendall('end'.encode())
        else:
            pass


while True:
    try:
    	# 被動接受客戶端連接,由於設置了settimeout,爲非阻塞
        client, addr = server_sock.accept()
        print('...connnecting from:', addr)
    except Exception as err:
        length = len(sub_threads)
        while length:
            thread = sub_threads.pop(0)
            sub_id = thread.ident
            # 等待線程結束
            thread.join(0.1)
            if thread.isAlive():
                sub_threads.append(thread)
            else:
                print('kll sub thread', sub_id)
            length -= 1
    else:
        _thread = threading.Thread(target=handle, name='sub thread', args=(client,))
        client.setblocking(1)
        _thread.start()
        sub_threads.append(_thread)
        
	# 如果沒有客戶端連接,關閉socket
    if len(sub_threads) <= 0:
        server_sock.close()
        break

client端實現

from socket import *
import sys

HOST = '127.0.0.1'
PORT = 12345
BUFSIZ = 1024
ADDR = (HOST, PORT)

# 創建套接字
client_sock = socket(AF_INET, SOCK_STREAM)
try:
    # 連接服務器端,參數必須是元組格式
    client_sock.connect(ADDR)
except Exception:
    client_sock.close()
    sys.exit()

send_data = '100'
# sendall(): 完整發送數據,內部循環調用s.send(bytes)
# send(bytes): 發送數據,python3發送數據的格式必須爲bytes格式
client_sock.sendall(send_data.encode())

while True:
    # 接收數據,BUFSIZ爲一次數據接收的大小
    recv_data = client_sock.recv(BUFSIZ)
    print('recv_data: ', recv_data)
    if not recv_data:
        # 關閉套接字
        client_sock.close()
        break
    recv_data_str = recv_data.decode('utf-8')
    if 'file_name' in recv_data_str:
        recv_file = recv_data_str[recv_data_str.find(':') + 1:]
    elif 'end' in recv_data_str:
        client_sock.close()
        break
    else:
        fd = open(recv_file, 'a')
        fd.write(recv_data_str)
        fd.close()

socket模塊

參考文檔

  • socket.socket(socket_family,socket_type,protocol=0)

    socket_family可以是如下參數:

     socket.AF_INET IPv4(默認)
    
     socket.AF_INET6 IPv6
    
     socket.AF_UNIX 只能夠用於單一的Unix系統進程間通信
    

    socket_type可以是如下參數:

     socket.SOCK_STREAM  流式socket , for TCP (默認)
    
     socket.SOCK_DGRAM   數據報式socket , for UDP
    
     socket.SOCK_RAW 原始套接字,普通的套接字無法處理ICMP、IGMP等網絡報文,而SOCK_RAW可以;其次,SOCK_RAW也可以處理特殊的IPv4報文;此外,利用原始套接字,可以通過IP_HDRINCL套接字選項由用戶構造IP頭。
    
     socket.SOCK_RDM 是一種可靠的UDP形式,即保證交付數據報但不保證順序。
    
     socket.SOCK_SEQPACKET 可靠的連續數據包服務
    

    protocol參數:

     0 (默認)與特定的地址家族相關的協議,如果是 0 ,則系統就會根據地址格式和套接類別,自動選擇一個合適的協議
    
  • 套接字對象內建方法

    服務器端套接字函數

     s.bind()   綁定地址(ip地址,端口)到套接字,參數必須是元組的格式
    
     s.listen(MAX)  開始監聽,MAX爲最大掛起的連接數
    
     s.accept()  被動接受客戶端連接,阻塞,等待連接
    

    客戶端套接字函數

     s.connect()  連接服務器端,參數必須是元組格式
    

    公共用途的套接字函數

     s.recv(1024)  接收數據,1024爲一次數據接收的大小
    
     s.send(bytes)  發送T數據,python3發送數據的格式必須爲bytes格式
    
     s.sendall()  完整發送數據,內部循環調用send
    
     s.close()  關閉套接字
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章