問題
你想實現乙個伺服器,通過tcp協議和客戶端通訊。
解決方案
建立乙個tcp伺服器的乙個簡單方法是使用 socketserver 庫。例如,下面是乙個簡單的應答伺服器:
from socketserver import baserequesthandler, tcpserver
class echohandler(baserequesthandler):
def handle(self):
print('got connection from', self.client_address)
while true:
msg = self.request.recv(8192)
if not msg:
break
self.request.send(msg)
if __name__ == '__main__':
serv = tcpserver(('', 20000), echohandler)
serv.serve_forever()
在這段**中,你定義了乙個特殊的處理類,實現了乙個 handle() 方法,用來為客戶端連線服務。 request 屬性是客戶端socket,client_address 有客戶端位址。 為了測試這個伺服器,執行它並開啟另外乙個python程序連線這個伺服器:
>>> from socket import socket, af_inet, sock_stream
>>> s = socket(af_inet, sock_stream)
>>> s.connect(('localhost', 20000))
>>> s.send(b'hello')
5>>> s.recv(8192)
b'hello'
>>>
很多時候,可以很容易的定義乙個不同的處理器。下面是乙個使用 streamrequesthandler 基類將乙個類檔案介面放置在底層socket上的例子:
from socketserver import streamrequesthandler, tcpserver
class echohandler(streamrequesthandler):
def handle(self):
print('got connection from', self.client_address)
# self.rfile is a file-like object for reading
for line in self.rfile:
# self.wfile is a file-like object for writing
self.wfile.write(line)
if __name__ == '__main__':
serv = tcpserver(('', 20000), echohandler)
serv.serve_forever()
討論socketserver 可以讓我們很容易的建立簡單的tcp伺服器。 但是,你需要注意的是,預設情況下這種伺服器是單執行緒的,一次只能為乙個客戶端連線服務。 如果你想處理多個客戶端,可以初始化乙個 forkingtcpserver 或者是 threadingtcpserver 物件。例如:
from socketserver import threadingtcpserver
if __name__ == '__main__':
serv = threadingtcpserver(('', 20000), echohandler)
serv.serve_forever()
使用fork或執行緒伺服器有個潛在問題就是它們會為每個客戶端連線建立乙個新的程序或執行緒。 由於客戶端連線數是沒有限制的,因此乙個惡意的黑客可以同時傳送大量的連線讓程式設計客棧你的伺服器奔潰。
如果你擔心這個問題,你可以建立乙個預先分配大小的工作執行緒池或程序池。 你先建立乙個普通的非執行緒伺服器,然後在乙個執行緒池中使用 serve_forever() 方法來啟動它們。
if __name__ == '__main__':
from threading import thread
nworkers = 16
serv = tcpserver(('', 20000), echohandler)
for n in range(nworkers):
t = thread(target=serv.serve_forever)
t.daemon = true
t.start()
serv.serve_forever()
一般來講,乙個 tcpserver 在例項化的時候會繫結並啟用相應的 socket 。 不過,有時候你想通過設定某些選項去調整底下的 socket` ,可以設定引數 bind_and_activate=false 。如下:
if __name__ == '__main__':
serv = tcpserver(('', 20000), echoh程式設計客棧andler, bind_and_activate=false)
# set up various socket options
serv.socket.setsockopt(socket.sol_socket, socket.so_reuseaddr, true)
# bind and activate
serv.server_b
serv.server_activate()
serv.serve_forever()
上面的 socket 選項是乙個非常普遍的配置項,它允許伺服器重新繫結乙個之前使用過的埠號。 由於要被經常使用到,它被放置到類變數中,可以直接在 tcpserver 上面設定。 在例項化伺服器的時候去設定它的值,如下所示:
if __name__ == '__ma程式設計客棧in__':
tcpserver.allow_reuse_address = true
serv = tcpserver(('', 20000), echohandler)
serv.serve_forever()
在上面示例中,我們演示了兩種不同的處理器基類( baserequesthandler 和 streamrequesthandler )。 streamrequesthandler 更加靈活點,能通過設定其他的類變數來支援一些新的特性。比如:
import socket
class echohandler(streamrequesthandler):
# optional settings (defaults 程式設計客棧shown)
timeout = 5 # timeout on all socket operations
rbufsize = -1 # read buffer size
wbufsize = 0 # write buffer size
disable_nagle_algorithm = false # sets tcp_nodelay socket option
def handle(self):
print('got connection from', self.client_address)
try:
for line in self.rfile:
# self.wfile is a file-like object for writing
self.wfile.write(line)
except socket.timeout:
print('timed out!')
最後,還需要注意的是絕大部分python的高層網路模組(比如http、xml-rpc等)都是建立在 socketserver 功能之上。 也就是說,直接使用 socket 庫來實現伺服器也並不是很難。 下面是乙個使用 socket 直接程式設計實現的乙個伺服器簡單例子:
from socket import socket, af_inet, sock_stream
def echo_handler(address, client_sock):
print('got connection from {}'.format(address))
while true:
msg = client_sock.recv(8192)
if not msg:
break
client_sock.sendall(msg)
client_sock.close()
def echo_server(address, backlog=5):
sock = socket(af_inet, sock_stream)
sock.bind(address)
sock.listen(backlog)
while true:
client_sock, client_addr = sock.accept()
echo_handler(client_addr, client_sock)
if __name__ == '__main__':
echo_server(('', 20000))
簡單TCP伺服器建立
簡單tcp伺服器建立 實現tcp伺服器的建立,實現迴圈與客戶端聊天,並且獲取客戶端資訊.tcp程式設計步驟 1 建立套接字socket 買手機.2 套接字繫結 bind 繫結手機卡.3 監聽套接字 listen 等待其他人打 4 接受客戶端請求 accept 接 進行資料的互動過程.通話內容.5 關...
swoole 建立tcp伺服器
server.php 建立tcp伺服器 date 2019 1 15 serv new swoole server 127.0.0.1 9501 監聽連線進入事件 serv on connect function serv,fd 監聽資料接收事件 serv on receive function s...
Web入門 建立TCP伺服器
from socket import from time import ctime host port 21567 bufsize 1024 addr host,port tcpsersock socket af inet,sock stream 建立伺服器套接字 tcpsersock.bind a...