python網絡編程,socket編程

本文簡要介紹對套接字的網絡編程。套接字是結算及網絡數據結構,體現的是“通信端點”的概念。網絡應用程序在進行任何通信之前,必須先創建套接字。

一、主要函數介紹:

Python中的網絡編程,主要使用socket模塊的函數。

socket =》創建套接字對象,socket(s ocket_family ,  socket_type ,  protocol =0)

服務器端的方法:

bind =》綁定地址到套接字

listen =》啓動TCP監聽

accept =》 接受客戶端連接

客戶端的方法:

connect =》初始化一個TCP服務連接

數據發送和接收:

recv =》接收數據

send =》發送數據


二、服務器端簡單的socket編程

1、創建socket:

import socket
from time import ctime

HOST = ''
PORT = 21567
BUFSIZE = 100 #一般取1024,可以自己根據需要調整。
ADDR = (HOST, PORT)

# 創建socket並監聽本地端口.
tcpServerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpServerSock.bind(ADDR)
tcpServerSock.listen(5)
2、接受客戶端連接,接收併發送數據

print("等待連接......")
tcpClientSock, addr = tcpServerSock.accept()
print("... 客戶端的地址爲:", addr)
while True:
#內循環,處理客戶端數據的發送和接收。
data = tcpClientSock.recv(BUFSIZE)
if not data:
break
recData = data.decode() #二進制數據轉換爲字符串。默認utf-8
print("從客戶端收到的數據:", recData)
sendData = "[%s] %s"%(ctime(), recData)
tcpClientSock.send(sendData.encode())
tcpClientSock.close()

tcpServerSock.close()

三、客戶端socket編程

1、建立TCP連接

import socket

HOST = 'LOCALHOST'
PORT = 21567
BUFSIZE = 100
ADDR = (HOST, PORT)

tcpClientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpClientSock.connect(ADDR)
2、定義發送函數

def send01(sock, msg):
# 在網絡不忙的時候,send函數每一次都會將全部的數據發送出去,一幫情況下會工作的很好。
sock.send(msg.encode())
3、發送數據到服務器並接收服務器的數據

data = input('> ')
if not data:
break
sendtotal(tcpClientSock, data)
data = tcpClientSock.recv(BUFSIZE)
if not data:
break
recData = data.decode() #將二進制數據轉換爲字符串數據。
print("從服務器上收到的數據:%s"%(recData))

4、網絡繁忙時發送數據的方法

def sendtotal(sock, msg):
#判斷send發送的字節數, 直到全部發送完。
totalsent = 0
data = msg.encode()
datalen = len(data)
while totalsent < datalen:
sent = sock.send(data[totalsent:])
if sent == 0:
raise RuntimeError("socket連接中斷")
totalsent = totalsent + sent

四、併發socket編程

上述簡單的socket編程方法,最多隻能處理一個客戶端的連接。python具有強大的線程處理能力,我們可以將線程與socket編程混合到一起,就可以同時處理多個客戶端的連接。

1、自定義socket線程類:

class SocketThread(threading.Thread):
"""自定義socket線程類"""
def __init__(self, sock):
threading.Thread.__init__(self)
self.sock = sock

def run(self):
while True:
# 內循環,處理客戶端數據的發送和接收。
data = self.sock.recv(BUFSIZE)
if not data:
break
recData = data.decode() # 二進制數據轉換爲字符串。默認utf-8
print("從客戶端收到的數據:", recData)
sendData = "[%s] %s" % (ctime(), recData)
self.sock.send(sendData.encode())
self.sock.close()
2、SocketThread的使用

def client_thread(sock):
"""創建socket線程"""
t = SocketThread(sock)
return t
pass

#外循環,等待客戶端連接
while True:
print("等待連接......")
tcpClientSock, addr = tcpServerSock.accept()
print("... 客戶端的地址爲:", addr)
ct = client_thread(tcpClientSock)
ct.start() #啓動線程

5、非阻塞socket編程

在使用線程來處理多個socket連接的問題時,受限於機器資源,線程是昂貴且有限的資源,同時處理的socket連接數畢竟有限。

下面就介紹一下python中非阻塞socket是如何處理的。

1、簡介:

非阻塞socket編程主要依賴於select模塊,該模塊提供了特定平臺的I/O監視函數。最輕便的方法就是POSIX功能的select()函數,在unix和windows平臺上都可用。

readable, writable, exceptional = select.select(inputs, outputs, inputs)

select方法會返回三個socket列表,分別爲讀列表,寫列表,異常列表,然後分別對這三個列表的socket進行處理。

2、select方法的使用:

import socket
import select
import queue
from time import ctime

HOST = ''
PORT = 21567
BUFSIZE = 1024 #一般取1024,可以自己根據需要調整。
ADDR = (HOST, PORT)

# 創建socket並監聽本地端口.
tcpServerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpServerSock.setblocking(0)
tcpServerSock.bind(ADDR)
tcpServerSock.listen(5)

# 準備讀數據的socket列表。
inputSockets = [tcpServerSock]
#準備發送數據的socket列表。
outputSockets = []
#輸出的消息隊列。
message_queues = {}
print("等待連接......")
readable, writable, exceptional = select.select(inputSockets, outputSockets, inputSockets)
3、對讀socket列表的處理:

for s in readable:
#處理讀的socket
if s is tcpServerSock:
clientConnection, addr = tcpServerSock.accept()
print("... 客戶端的地址爲:", addr)
clientConnection.setblocking(0)
inputSockets.append(clientConnection) #放到讀取數據列表中。
#每一個connection一個發送數據的隊列。
message_queues[clientConnection] = queue.Queue()
else:
data = s.recv(BUFSIZE)
if data:
print("從%s接收到數據%s" % (s.getpeername(), data.decode()))
message_queues[s].put(data)
if s not in outputSockets:
outputSockets.append(s)
else:
print("關閉客戶端%s,沒有讀取到數據." % (addr))
if s in outputSockets:
outputSockets.remove(s)
inputSockets.remove(s)
s.close()
#刪除當前socket對應的消息隊列。
del message_queues[s]
4、對寫socket列表的處理:

#處理數據發送隊列。
for s in writable:
try:
next_msg = message_queues[s].get_nowait()
except queue.Empty:
print("%s的輸出隊列爲空" % ("ddddd"))
outputSockets.remove(s)
else:
print("發送數據 %s 到 %s" % (next_msg, s.getpeername()))
s.send(next_msg)
5、對異常socket列表的處理:

for s in exceptional:
print("與%s的通信產生異常,連接將被斷開"%(s.getpeername()))
inputSockets.remove(s)
if s in outputSockets:
outputSockets.remove(s)
s.close()
del message_queues[s]

備註:

完整源代碼可以搜索:python網絡編程




發佈了37 篇原創文章 · 獲贊 7 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章