和客戶(hù)端編程相比,服務(wù)器編程就要復(fù)雜一些。
服務(wù)器進(jìn)程首先要綁定一個(gè)端口并監(jiān)聽(tīng)來(lái)自其他客戶(hù)端的連接。如果某個(gè)客戶(hù)端連接過(guò)來(lái)了,服務(wù)器就與該客戶(hù)端建立Socket連接,隨后的通信就靠這個(gè)Socket連接了。
所以,服務(wù)器會(huì)打開(kāi)固定端口(比如80)監(jiān)聽(tīng),每來(lái)一個(gè)客戶(hù)端連接,就創(chuàng)建該Socket連接。由于服務(wù)器會(huì)有大量來(lái)自客戶(hù)端的連接,所以,服務(wù)器要能夠區(qū)分一個(gè)Socket連接是和哪個(gè)客戶(hù)端綁定的。一個(gè)Socket依賴(lài)4項(xiàng):服務(wù)器地址、服務(wù)器端口、客戶(hù)端地址、客戶(hù)端端口來(lái)唯一確定一個(gè)Socket。
但是服務(wù)器還需要同時(shí)響應(yīng)多個(gè)客戶(hù)端的請(qǐng)求,所以,每個(gè)連接都需要一個(gè)新的進(jìn)程或者新的線程來(lái)處理,否則,服務(wù)器一次就只能服務(wù)一個(gè)客戶(hù)端了。
我們來(lái)編寫(xiě)一個(gè)簡(jiǎn)單的服務(wù)器程序,它接收客戶(hù)端連接,把客戶(hù)端發(fā)過(guò)來(lái)的字符串加上Hello再發(fā)回去。
多線程的echo服務(wù)器的缺點(diǎn)是:
對(duì)于每一個(gè)連接都要?jiǎng)?chuàng)建一個(gè)線程,這個(gè)開(kāi)銷(xiāo)還是很大的。但是對(duì)于單線程的服務(wù)器,它起碼解決了阻塞的問(wèn)題。對(duì)于它的改進(jìn)方法,參考http://www.lxweimin.com/p/8a360a3f13aa
server端代碼:
#coding:utf-8
import socket
import threading
import time
def tcplink(sock, addr):
print('Accept new connection from %s:%s...' % addr)
sock.send(b'Welcome!')
while True:
data = sock.recv(1024)
time.sleep(1)
if not data or data.decode('utf-8') == 'exit':
break
sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
sock.close()
print('Connection from %s:%s closed.' % addr)
#建立一個(gè)socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#監(jiān)聽(tīng)9999端口
s.bind(('127.0.0.1', 9999))
#緊接著,調(diào)用listen()方法開(kāi)始監(jiān)聽(tīng)端口,傳入的參數(shù)指定等待連接的最大數(shù)量
s.listen(5)
print('Waiting for connection...')
while True:
# 接受一個(gè)新連接: 返回的sock用來(lái)通信,addr是客戶(hù)機(jī)的地址
sock, addr = s.accept()
# 創(chuàng)建新線程來(lái)處理TCP連接:
t = threading.Thread(target=tcplink, args=(sock, addr))
t.start()
<br />
client 代碼:
#coding:utf-8
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立連接:
s.connect(('127.0.0.1', 9999))
# 接收歡迎消息:
print(s.recv(1024).decode('utf-8'))
for data in [b'Michael', b'Tracy', b'Sarah']:
# 發(fā)送數(shù)據(jù):
s.send(data)
print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()
運(yùn)行結(jié)果:
相關(guān)文章:
一個(gè)基于python的單線程的echo服務(wù)器
http://www.lxweimin.com/p/8f1941c4a549
基于python的一個(gè)多線程echo服務(wù)器
http://www.lxweimin.com/p/2ffde49b55c3
一個(gè)基于select模型的echo服務(wù)器
http://www.lxweimin.com/p/8a360a3f13aa
關(guān)于select,poll,epoll3個(gè)網(wǎng)絡(luò)編程異步模型的區(qū)別
http://www.lxweimin.com/p/3bf72e232fb8