測試代碼
我們在本機模擬一次socket中的連接,即將服務端與客戶端都放在本地,並且在服務端模擬了對於客戶端發送數據的處理並返回。
代碼中的每個函數的具體用法已放在注釋中。
服務端:
# -*- coding: utf-8 -*-
import socket
import threading
def handle_tcp(sock, addr):
print("Establishing a connection from %s:%s" % addr)
# 發送TCP數據,將string中的數據發送到連接的套接字。
sock.send(b'Start!')
while True:
# 接收TCP數據,數據以字符串形式返回,bufsize指定要接收的最大數據量。flag提供有關消息的其他信息,通常可以忽略。
# bufsize的單位為bytes
data = sock.recv(1024)
if not data:
break
sock.send(b'Hello, %s!' % data)
# 關閉套接字
sock.close()
if __name__ == '__main__':
# 我們用 socket()函數來創建套接字,語法為socket.socket([family[, type[, proto]]])
# family: 套接字家族可以使AF_UNIX或者AF_INET
# type:套接字類型可以根據是面向連接的還是非連接分為SOCK_STREAM或SOCK_DGRAM
# protocol: 一般不填默認為0.
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 綁定地址(host,port)到套接字, 在AF_INET下,以元組(host,port)的形式表示地址。
s.bind(('127.0.0.1', 80))
# 開始TCP監聽。backlog指定在拒絕連接之前,操作系統可以掛起的最大連接數量。該值至少為1,大部分應用程序設為5就可以了。
s.listen(5)
while True:
# 被動接受TCP客戶端連接,(阻塞式)等待連接的到來
sock, addr = s.accept()
print ("got a connection request")
# 開啟一個新的線程來處理這個socket請求
t = threading.Thread(target=handle_tcp, args=(sock, addr))
t.start()
客戶端:
# -*- coding: utf-8 -*-
import socket
import time
if __name__ == '__main__':
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 主動初始化TCP服務器連接,。一般address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。
s.connect(('127.0.0.1', 80))
print(s.recv(1024))
for data in [b'one', b'two', b'three']:
s.send(data)
time.sleep(1)
print(s.recv(1024))
time.sleep(1200)
s.close()
測試結果
服務端輸出:
got a connection request
Establishing a connection from 127.0.0.1:61705
說明服務被正確地調起,並且客戶機的端口為61705
客戶端輸出:
Start!
Hello, one!
Hello, two!
Hello, three!
說明客戶端正確地連接到服務端,成功發送數據,並且服務端將數據進行處理並返回(“hello, one”這些為服務端返回)。
查看端口占用
先運行服務端的程序,然后打開cmd,鍵入:
Netstat -ano|findstr "127.0.0.1:80"
輸出:
幾列數據分別為:
協議 | 本地地址 | 外部地址 | 狀態 | PID
我們再去看一下現在運行的python程序是不是能夠對應到這個PID:
tasklist | findstr python
沒有問題,PID6984確實是我們剛剛運行的python的程序的進程。
然后,再運行客戶端的代碼,然后在cmd中重新查看一次端口與PID:
可以看到,這里的這兩個端口即為我們的服務端的進程與客戶端的python的程序,且前者的源/目的地址,即為后者的目的/源地址。