Python3 Socket

Socket

socket介紹

socket意爲套接字,是應用層與傳輸層TCP/IP,UDP之間通信的中間軟件抽象層,它是一組接口。使用時只需遵循socket的格式與規定去編程,讓socket組織數據以符合TCP/UDP協議進行數據的傳輸。

img

socket的工作流程

img

先從服務端說起,服務端先初始化socket --> 爲此socket綁定端口(bind) --> 監聽此端口(listen) --> 調用accept阻塞socket,直到有客戶端連接 --> 如果此時客戶端連接成功(connect),即與服務端完整建立連接,即可開始發送數據請求(write) --> 服務器端接收請求並處理請求(read),然後把迴應數據發送給客戶端(write) --> 客戶端讀取響應內容(read) --> 關閉連接,交互結束(close)

scoket初始化->socket.socket()

socket.socket(socket_family,socket_type,protocal=0)

socket_family

AF_INET(ipv4)
AF_INET6 (ipv6)
AF_UNIX(UNIX之間通信,絕對路徑名)

socket_type

#   SOCK_STREAM 提供有序的、可靠的、雙向的和基於連接的字節流服務,當使用Internet地址族時使用TCP;一般爲面向連接的TCP

#   SOCK_DGRAM 支持無連接的、不可靠的和使用固定大小(通常很小)緩衝區的數據報服務,當使用Internet地址族使用UDP;一般爲非連接的UDP

#   SOCK_RAW 原始套接字,允許對底層協議如IP或ICMP進行直接訪問,可以用於自定義協議的開發。

protocal

#	IPPROTO_TCP,TCP協議

# 	IPPROTO_UDP,UPD協議

# 	0,如果指定爲0,表示由內核根據so_type指定默認的通信協議

TCP/IP+ipv4

s.socket(socket.AF_INET, socket.SOCK_STREAM)

服務端套接字

s.bind()

用於綁定(主機/ip,端口)到socket套接字, 在AF_INET下,以元組(host,port)的形式表示地址。

s.bind(('xxx.xxx.xxx.xxx',port))

s.listen()

開始TCP監聽。backlog指定在拒絕連接之前,操作系統可以掛起的最大連接數量。該值至少爲1,大部分應用程序設爲5就可以了。

ps:udp不支持listen()

s.listen(5)

s.accept()

被動接受TCP客戶端連接,(阻塞式)等待連接的到來

ps: udp不支持

conn,addr = s.accept()

關於accept()返回值在官方文檔是這麼說的

The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection.

有兩個返回值conn和address,第一個返回值爲新的 socket 對象可用於發送和接受數據,形式大致如下

<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.124.141', 12345), raddr=('192.168.124.1', 15563)>

address爲一個元組,元組包含遠端連接的ip地址和端口,形如

('192.168.124.1', 15563)

客戶端套接字

s.connect()

主動初始化TCP服務器連接。一般address的格式爲元組(主機/ip,port),如果連接出錯,返回socket.error錯誤。

s.connect(('192.168.124.1',22222))

s.connect_ex()

connect()函數的擴展版本,出錯時返回出錯碼,而不是拋出異常

公共用途的套接字函數

s.recv()

socket.recv(bufsize[, flags])

從套接字接收數據。返回值是表示接收到的數據的bytes對象。bufsize指定一次接收的最大數據量。一般爲1024

s.recv(1024)

s.send()

發送數據,將數據發送到socket套接字。(send在待發送數據量大於己端緩存區剩餘空間時,數據丟失,不會發完)

s.send('This is Socket Client!'.encode('utf-8'))

s.sendall()

發送完整的TCP數據(本質就是循環調用send,sendall在待發送數據量大於己端緩存區剩餘空間時,數據不丟失,循環調用send直到發完)

s.close()

關閉socket 套接字

簡單例子 TCP連接

SocketServer.py

#!/usr/bin/python3
#-*- coding:UTF-8 -*-

import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 
phone.bind(('192.168.124.141',12345)) 

phone.listen(5) 

conn,addr=phone.accept() 
print(conn,addr)
print('Remote IP Address is',addr)

client_msg=conn.recv(1024) 
print('client msg: %s' %client_msg)
conn.send(client_msg。upper()) 

conn.close()
s.close()

SocketClient.py

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect(('192.168.124.141', 12345))

s.send('this is socket client!'.encode('utf-8'))

res_msg = s.recv(1024)
print(res_msg)

s.close

服務端

image-20201124233020283

客戶端

image-20201124233105709

簡單例子UDP連接

SocketServer.py

#!/usr/bin/python3
#-*- coding:UTF-8 -*-

import socket


s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

ip = '192.168.124.141'
port = 12346

s.bind((ip,port))

recv_data,addr = s.recvfrom(1024)
print('Client Send Message: %s' %recv_data)

server_send_data = 'this is server!!!'

s.sendto(server_send_data.encode(),addr)

s.close()

SocketClient.py

import socket


s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

s.sendto('this is socket client!!!'.encode('utf-8'),('192.168.124.141',12346))

res_msg,addr = s.recvfrom(1024)

print(res_msg)

s.close()

服務端

image-20201125001423390

客戶端

image-20201125001439186

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章