Python3 Socket編程(個人總結)

概要:Socket又稱"套接字",應用程序通常通過"套接字"向網絡發出請求或者應答網絡請求,使主機間或者一臺計算機上的進程間可以通訊。

一、套接字對象

Python 中,我們用 socket()函數來創建套接字,語法格式如下:

socket.socket([family[, type[, proto]]])

  • family: 套接字家族可以使AF_UNIX或者AF_INET
  • type: 套接字類型可以根據是面向連接的還是非連接分爲SOCK_STREAMSOCK_DGRAM
  • protocol: 默認值.

構造器定義如下:

 def __init__(self, family=-1, type=-1, proto=-1, fileno=None):
        # For user code address family and type values are IntEnum members, but
        # for the underlying _socket.socket they're just integers. The
        # constructor of _socket.socket converts the given argument to an
        # integer automatically.
        if fileno is None:
            if family == -1:
                family = AF_INET
            if type == -1:
                type = SOCK_STREAM
            if proto == -1:
                proto = 0
        _socket.socket.__init__(self, family, type, proto, fileno)
        self._io_refs = 0
        self._closed = False

二、內建函數(參考菜鳥教程)

函數 描述
bind() 綁定地址(host,port)到套接字, 在AF_INET下,以元組(host,port)的形式表示地址。
listen() 開始TCP監聽。backlog指定在拒絕連接之前,操作系統可以掛起的最大連接數量。該值至少爲1,大部分應用程序設爲5就可以了。
accept() 被動接受TCP客戶端連接,(阻塞式)等待連接的到來
connect() 主動初始化TCP服務器連接,。一般address的格式爲元組(hostname,port),如果連接出錯,返回socket.error錯誤。
connect_ex() connect()函數的擴展版本,出錯時返回出錯碼,而不是拋出異常
recv() 接收TCP數據,數據以字符串形式返回,bufsize指定要接收的最大數據量。flag提供有關消息的其他信息,通常可以忽略。
send() 發送TCP數據,將string中的數據發送到連接的套接字。返回值是要發送的字節數量,該數量可能小於string的字節大小。
sendall() 完整發送TCP數據,完整發送TCP數據。將string中的數據發送到連接的套接字,但在返回之前會嘗試發送所有數據。成功返回None,失敗則拋出異常。
recvfrom() 接收UDP數據,與recv()類似,但返回值是(data,address)。其中data是包含接收數據的字符串,address是發送數據的套接字地址。
sendto() 發送UDP數據,將數據發送到套接字,address是形式爲(ipaddr,port)的元組,指定遠程地址。返回值是發送的字節數。
close() 關閉套接字
getpeername() 返回連接套接字的遠程地址。返回值通常是元組(ipaddr,port)。
getsockname() 返回套接字自己的地址。通常是一個元組(ipaddr,port)
setsockopt(level,optname,value) 設置給定套接字選項的值。
getsockopt(level,optname[.buflen]) 返回套接字選項的值。
settimeout(timeout) 設置套接字操作的超時期,timeout是一個浮點數,單位是秒。值爲None表示沒有超時期。一般,超時期應該在剛創建套接字時設置,因爲它們可能用於連接的操作(如connect())
gettimeout() 返回當前超時期的值,單位是秒,如果沒有設置超時期,則返回None。
fileno() 返回套接字的文件描述符。
setblocking(flag) 如果flag爲0,則將套接字設爲非阻塞模式,否則將套接字設爲阻塞模式(默認值)。非阻塞模式下,如果調用recv()沒有發現任何數據,或send()調用無法立即發送數據,那麼將引起socket.error異常。
makefile() 創建一個與該套接字相關連的文件

三、通訊示例

  • 服務端
#!/usr/bin/python3

import socket
import threading

# 創建 socket 對象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 獲取本地主機名
host = socket.gethostname()

port = 6666

# 綁定IP和端口號
server_socket.bind((host, port))

# 設置最大連接數
server_socket.listen(10)

client_socket, addr = server_socket.accept()

print("客戶端 %s已連接" % (addr,))


def print_msg():
    while True:
        try:
            data = client_socket.recv(1024).decode()
            if data == 'exit':
                    client_socket.close()
            else:
                print(">>> " + data)
        except ConnectionResetError:
            print("客戶端 %s已下線!" % (addr,))
            break


# 啓動異步線程用於輸出客戶端信息
thread = threading.Thread(name="Server", target=print_msg)
thread.start()

while True:
    send_msg = input()
    client_socket.send(send_msg.encode('utf-8'))

  • 客戶端
#!/usr/bin/python3

import socket
import threading


# 創建 socket 對象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 獲取本地主機名
host = socket.gethostname()

# 設置端口號
port = 6666

# 連接服務,指定主機和端口
client_socket.connect((host, port))


def print_msg():
    while True:
        try:
            msg = client_socket.recv(1024).decode()
            print(">>> " + msg)
        except Exception:
            print("已成功下線!")
            break


# 啓動異步線程用於輸出服務端信息
thread = threading.Thread(name="Client", target=print_msg)
thread.start()

send_msg = input()

while send_msg != 'exit':
    client_socket.send(send_msg.encode('utf-8'))
    send_msg = input()
else:
    client_socket.close()

  • 結果

服務端

客戶端 ('192.168.0.104', 53131)已連接
>>> 你好,在嗎?
在,怎麼了?
>>> 沒事,再見
客戶端 ('192.168.0.104', 53131)已下線!

客戶端

你好,在嗎?
>>> 在,怎麼了?
沒事,再見
exit
已成功下線!
發佈了36 篇原創文章 · 獲贊 31 · 訪問量 46萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章