socket(套接字)起源于UNIX,主要用于網絡進程間通訊,它是在應用層和傳輸層之間的一個軟件抽象層,它把TCP/IP復雜的操作抽象為幾個簡單的接口供應用層調用來實現進程在網絡中的通信。因為在Unix中一切皆為文件,所以socket通過"open—read/write—close"模式來實現進程在網絡中的通信。服務器和客戶端各自維護一個"文件",建立連接后相當于打開了文件,各自可以向自己文件寫入內容供對方讀取或者讀取對方內容,通訊結束時則關閉文件。
TCP連接流程
socket主要以"open—read/write—close"的模式來實現客戶端和服務器之間TCP協議的連接,交互流程如下圖所示。TCP服務器的建立可以歸納這幾步:1)創建socket(套接字);2)綁定socket的ip地址和端口;3)監聽客戶端的連接請求;4)接受客戶端的連接請求;5)與客戶端對話;6)關閉連接。TCP客戶端的創建可總結為這幾步:1)創建socket(套接字);2)連接服務器socket;3)與服務器對話;4)關閉連接。
需要注意的是TCP客戶端連接到服務器的ip和端口要與TCP服務器監聽的ip和端口相同,服務器調用listen()開始監聽端口,而后調用accept()時刻準備接受客戶端的連接請求,此時服務器處于阻塞狀態,直到服務器監聽到客戶端的請求后,接收請求并建立連接為止。
TCP服務器/客戶端例程
提供給大家兩個Python實現socket連接例程,一個為TCP服務器和客戶端的短連接例程,即服務器接受客戶端連接后創建一個線程,在線程中與客戶端收發數據后關閉連接,另一個為TCP服務器和客戶端的長連接例程,服務器與客戶端建立連接后彼此循環收發數據,不關閉連接。
這里要注意的是服務器接收客戶端發送數據時是處于阻塞狀態的。server.close()是關閉服務端的socket程序本身的連接,關閉后整個服務端socket程序就退出運行。client_socket.close()是關閉服務端socket程序與客戶端的連接,關閉后服務端的socket程序仍然還在運行。
TCP服務器短連接實現
import socket import threading bind_ip = "127.0.0.1" bind_port = 12345 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((bind_ip, bind_port))#bind ip and port server.listen(5)#start listen max connection print "[*] listening on %s:%d" % (bind_ip, bind_port) def handle_client(client_socket): request = client_socket.recv(1024) print "[*] Received: %s" % request client_socket.send('ACK!') client_socket.close() while True: client, addr = server.accept() print "[*] Accepted connection from: %s:%d" % (addr[0], addr[1]) client_handler = threading.Thread(target=handle_client, args=(client,)) client_handler.start() server.close() TCP客戶端短連接實現 import socket target_host = '127.0.0.1' target_port = 12345 #Creat socket object AF_INET means use the normod IPv4 address and hots name;OCK_STREAM one tcp client client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((target_host, target_port)) client.send("i am TCP client") response = client.recv(4096) print response TCP服務器長連接實現 import socket import threading bind_ip = "127.0.0.1" bind_port = 12345 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((bind_ip, bind_port))#bind ip and port server.listen(5)#start listen max connection print "[*] listening on %s:%d" % (bind_ip, bind_port) while True: client, addr = server.accept() print "[*] Accepted connection from: %s:%d" % (addr[0], addr[1]) while True: request = client.recv(1024) print "[*] Received: %s" % request client.send('ACK!') print "[*] Sended: ACK!" client.close() server.close() TCP客戶端長連接實現 import socket target_host = '127.0.0.1' target_port = 12345 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((target_host, target_port)) while True: client.send("TCP client connect") response = client.recv(4096) print response