1. 程式人生 > >python網絡編程(八)

python網絡編程(八)

IE finally 空閑 while 因此 ddr tcp服務器 隊列 %s

單進程服務器

1. 完成一個簡單的TCP服務器

from socket import *

serSocket = socket(AF_INET, SOCK_STREAM)

# 重復使用綁定的信息
serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR  , 1)

localAddr = (‘‘, 7788)

serSocket.bind(localAddr)

serSocket.listen(5)

while True:

    print(-----主進程,,等待新客戶端的到來------)

    newSocket,destAddr 
= serSocket.accept() print(-----主進程,,接下來負責數據處理[%s]-----%str(destAddr)) try: while True: recvData = newSocket.recv(1024) if len(recvData)>0: print(recv[%s]:%s%(str(destAddr), recvData)) else: print([%s]客戶端已經關閉
%str(destAddr)) break finally: newSocket.close() serSocket.close()

2. 總結

  • 同一時刻只能為一個客戶進行服務,不能同時為多個客戶服務
  • 類似於找一個“明星”簽字一樣,客戶需要耐心等待才可以獲取到服務
  • 當服務器為一個客戶端服務時,而另外的客戶端發起了connect,只要服務器listen的隊列有空閑的位置,就會為這個新客戶端進行連接,並且客戶端可以發送數據,但當服務器為這個新客戶端服務時,可能一次性把所有數據接收完畢
  • 當recv接收數據時,返回值為空,即沒有返回數據,那麽意味著客戶端已經調用了close關閉了;因此服務器通過判斷recv接收數據是否為空 來判斷客戶端是否已經下線

多進程服務器

1. 多進程服務器

from socket import *
from multiprocessing import *
from time import sleep

# 處理客戶端的請求並為其服務
def dealWithClient(newSocket,destAddr):
    while True:
        recvData = newSocket.recv(1024)
        if len(recvData)>0:
            print(recv[%s]:%s%(str(destAddr), recvData))
        else:
            print([%s]客戶端已經關閉%str(destAddr))
            break

    newSocket.close()


def main():

    serSocket = socket(AF_INET, SOCK_STREAM)
    serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR  , 1)
    localAddr = (‘‘, 7788)
    serSocket.bind(localAddr)
    serSocket.listen(5)

    try:
        while True:
            print(-----主進程,,等待新客戶端的到來------)
            newSocket,destAddr = serSocket.accept()

            print(-----主進程,,接下來創建一個新的進程負責數據處理[%s]-----%str(destAddr))
            client = Process(target=dealWithClient, args=(newSocket,destAddr))
            client.start()

            #因為已經向子進程中copy了一份(引用),並且父進程中這個套接字也沒有用處了
            #所以關閉
            newSocket.close()
    finally:
        #當為所有的客戶端服務完之後再進行關閉,表示不再接收新的客戶端的鏈接
        serSocket.close()

if __name__ == __main__:
    main()

2. 總結

  • 通過為每個客戶端創建一個進程的方式,能夠同時為多個客戶端進行服務
  • 當客戶端不是特別多的時候,這種方式還行,如果有幾百上千個,就不可取了,因為每次創建進程等過程需要好較大的資源

多線程服務器

#coding=utf-8
from socket import *
from threading import Thread
from time import sleep

# 處理客戶端的請求並執行事情
def dealWithClient(newSocket,destAddr):
    while True:
        recvData = newSocket.recv(1024)
        if len(recvData)>0:
            print(recv[%s]:%s%(str(destAddr), recvData))
        else:
            print([%s]客戶端已經關閉%str(destAddr))
            break

    newSocket.close()


def main():

    serSocket = socket(AF_INET, SOCK_STREAM)
    serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR  , 1)
    localAddr = (‘‘, 7788)
    serSocket.bind(localAddr)
    serSocket.listen(5)

    try:
        while True:
            print(-----主進程,,等待新客戶端的到來------)
            newSocket,destAddr = serSocket.accept()

            print(-----主進程,,接下來創建一個新的進程負責數據處理[%s]-----%str(destAddr))
            client = Thread(target=dealWithClient, args=(newSocket,destAddr))
            client.start()

            #因為線程中共享這個套接字,如果關閉了會導致這個套接字不可用,
            #但是此時在線程中這個套接字可能還在收數據,因此不能關閉
            #newSocket.close() 
    finally:
        serSocket.close()

if __name__ == __main__:
    main()

 

python網絡編程(八)