TCP和并發(fā)服務(wù)器
與UDP不同的是,他是一個(gè)面向連接的,可靠的數(shù)據(jù)傳輸協(xié)議
TCP通信比較復(fù)雜
先寫(xiě)一個(gè)TCP服務(wù)器,一般步驟如下:
1、首先是要?jiǎng)?chuàng)建一個(gè)socket套接字:socket()
2、服務(wù)器一般是需要一個(gè)固定的IP地址和固定端口號(hào),服務(wù)器就要綁定這個(gè)IP地址和端口號(hào):bind()
3、客戶端連接服務(wù)器是是有一定的數(shù)量(允許最大連接數(shù))的,而這個(gè)數(shù)量是服務(wù)器設(shè)定的:listen()
4、上面3步是做被連接的準(zhǔn)備,這一步是來(lái)接受客戶端的數(shù)據(jù),在接受數(shù)據(jù)之前,服務(wù)器還是需要接受客戶端的socket套接字和IP地址:accept()
5、只有服務(wù)器和客戶端綁定相同的IP地址,服務(wù)器和客戶端才可以互相接收數(shù)據(jù)和發(fā)送數(shù)據(jù),常理來(lái)想,服務(wù)器是一只被開(kāi)啟的,也是一直接受數(shù)據(jù),所以在接受數(shù)據(jù)的過(guò)程中,我們需要無(wú)限循環(huán):recv()
6、如果我們要發(fā)送數(shù)據(jù)給客戶端,客戶端也需要綁定上面的地址,然后需要調(diào)用相應(yīng)的函數(shù)send()
import socket # TCP # 創(chuàng)建一個(gè)服務(wù)器socket套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 服務(wù)器的IP地址和端口號(hào) address = ( " 127.0.0.1 " , 9999 ) # 服務(wù)器綁定地址 server_socket.bind(address) # 設(shè)置服務(wù)器的最大連接數(shù) server_socket.listen(1 ) # 創(chuàng)建一個(gè)等待連接的客戶端socket套接字,accept()函數(shù)會(huì)返回兩個(gè)值,可以自行打印 client_socket, address = server_socket.accept() # 服務(wù)器需要不停的接受客戶端的發(fā)來(lái)的數(shù)據(jù) while True: """ 以防客戶端連接失敗,需要檢測(cè)異常 無(wú)論是接受數(shù)據(jù)還是發(fā)送數(shù)據(jù),我們需要將數(shù)據(jù)統(tǒng)一編碼和解碼 """ try : data = client_socket.recv(2048).decode( " UTF-8 " ) # 數(shù)據(jù)處理 print ( " 服務(wù)器接受的數(shù)據(jù): " , data) # 服務(wù)器接受的數(shù)據(jù):我是一個(gè)客戶端 client_socket.send( " 我是一個(gè)服務(wù)器 " .encode( " UTF-8 " )) except : break
再寫(xiě)一個(gè)TCP客戶端,一般步驟如下:
1、首先是要?jiǎng)?chuàng)建一個(gè)socket套接字:socket()
2、客戶端一般是不需要一個(gè)固定的IP地址和固定端口號(hào),連接服務(wù)器的時(shí)候系統(tǒng)會(huì)自動(dòng)分配端口號(hào)
3、客戶端連接服務(wù)器必須先知道服務(wù)器的IP地址和端口號(hào),然后在連接服務(wù)器:connect()
4、上面3步是做連接的準(zhǔn)備,這一步是來(lái)發(fā)送客戶端的數(shù)據(jù):send()
5、客戶端也可以一直接受服務(wù)器發(fā)來(lái)的數(shù)據(jù),所以在接受數(shù)據(jù)的過(guò)程中,我們需要無(wú)限循環(huán):recv()
import socket # 客戶端需要?jiǎng)?chuàng)建一個(gè)套接字 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 客戶端需要連接服務(wù)器,必須先知道服務(wù)器的IP地址和端口號(hào) address = ( " 127.0.0.1 " , 9999 ) # 連接服務(wù)器 client_socket.connect(address) # 這個(gè)數(shù)據(jù)是將要發(fā)送的數(shù)據(jù) data = " 我是一個(gè)客戶端 " client_socket.send(data.encode( " UTF-8 " )) while True: """ 以防服務(wù)器中斷退出,需要檢測(cè)異常 無(wú)論是接受數(shù)據(jù)還是發(fā)送數(shù)據(jù),我們需要將數(shù)據(jù)統(tǒng)一編碼和解碼 """ try : data = client_socket.recv(2048).decode( " UTF-8 " ) # 數(shù)據(jù)處理,這里打印出來(lái)并且將數(shù)據(jù)發(fā)回客戶端 print ( " 客戶端接受的數(shù)據(jù): " , data) except : break
?并發(fā)服務(wù)器,這里我只介紹多線程服務(wù)器,進(jìn)程和線程是差不多的)
在TCP服務(wù)器的原有基礎(chǔ)上增加一個(gè)線程,再將監(jiān)聽(tīng)數(shù)增加為5,就可以允許5個(gè)客戶端線程同時(shí)訪問(wèn),并且可同時(shí)發(fā)送和接受數(shù)據(jù)
import socket from threading import Thread # TCP # 創(chuàng)建一個(gè)服務(wù)器socket套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 服務(wù)器的IP地址和端口號(hào) address = ( " 127.0.0.1 " , 9999 ) def net_connect(): try : # 服務(wù)器綁定地址 server_socket.bind(address) # 設(shè)置服務(wù)器的最大連接數(shù) server_socket.listen(5 ) except : return # 創(chuàng)建線程 th = Thread(target= recv_data) th.start() def recv_data(): # 服務(wù)器需要不停的接受客戶端的發(fā)來(lái)的數(shù)據(jù) while True: """ 以防客戶端連接失敗,需要檢測(cè)異常 無(wú)論是接受數(shù)據(jù)還是發(fā)送數(shù)據(jù),我們需要將數(shù)據(jù)統(tǒng)一編碼和解碼 """ # 創(chuàng)建一個(gè)等待連接的客戶端socket套接字,accept()函數(shù)會(huì)返回兩個(gè)值,可以自行打印 client_socket, address = server_socket.accept() try : data = client_socket.recv(2048).decode( " UTF-8 " ) # 數(shù)據(jù)處理 print ( " 服務(wù)器接受的數(shù)據(jù): " , data) client_socket.send( " 我是一個(gè)服務(wù)器 " .encode( " UTF-8 " )) except : break net_connect()
?
在TCP客戶端上也增加一個(gè)線程,然后同時(shí)運(yùn)行多次這個(gè)客戶端程序:
import socket # 客戶端需要?jiǎng)?chuàng)建一個(gè)套接字 from threading import Thread client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 客戶端需要連接服務(wù)器,必須先知道服務(wù)器的IP地址和端口號(hào) address = ( " 127.0.0.1 " , 9999 ) def net_connect(): try : # 連接服務(wù)器 client_socket.connect(address) except : return th = Thread(target= recv_data) # th.setDaemon(True) th.start() def recv_data(): # 這個(gè)數(shù)據(jù)是將要發(fā)送的數(shù)據(jù) data = " 我是一個(gè)客戶端 " client_socket.send(data.encode( " UTF-8 " )) while True: """ 以防服務(wù)器中斷退出,需要檢測(cè)異常 無(wú)論是接受數(shù)據(jù)還是發(fā)送數(shù)據(jù),我們需要將數(shù)據(jù)統(tǒng)一編碼和解碼 """ try : data = client_socket.recv(2048).decode( " UTF-8 " ) # 數(shù)據(jù)處理,這里打印出來(lái)并且將數(shù)據(jù)發(fā)回客戶端 print ( " 客戶端接受的數(shù)據(jù): " , data) except : break net_connect()
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
