python基礎之socket


1、TCP sorcket:

server side(服務器端):

 1 import SocketServer
 2 class MyTCPHandler(SocketServer.BaseRequestHandler):
 3     def handle(self):
 4         self.data=self.request.recv(1024).strip()
 5         print "{} wrote".format(self.client_address[0])
 6         print self.data
 7         self.request.sendall(self.data.upper())
 8 if __name__=="__main__":
 9     HOST,PORT="localhost",9999
10     server=SocketServer.TCPServer((HOST,PORT),MyTCPHandler)
11     server.serve_forever()    

解釋:

第1句引進相關模塊;
第2句定義類MyTCPHandler,它是繼承自SocketServer的BaseRequestHandler類,該類還有相關的子類,下面會用到;
第3句重寫基類的handle()方法,有很多屬性可以直接用,比如self.request,請求,self.request.recv(1024).strip()的意思是從客戶端的請求那得到最大1kb的數據,並且數據.strip(),去掉前后的空格,中間的不會去掉的;
self.client_adress是客戶端的地址;
第7句是把得到的數據轉換成大寫發給客戶端;
第8句是只有在直接運行當前程序是才會運行到的;
HOST、PORT是主機地址和端口號;
第10句就是創建一個server對象,是基於TCPServer類創建的;
11句是啟動服務監聽的意思;

上面是一種創建TCP server的方法,下面還有一種基於BaseRequestHandler基類StreamRequestHandler,當然它還有一個基類DatagramRequestHandler,兩者有區別。

 1 import SocketServer
 2 class MyTCPHandler(SocketServer.StreamRequestHandler):
 3     def handle(self):
 4         self.data=self.rfile.readline().strip()
 5         print "{} wrote".format(self.client_address[0])
 6         print self.data
 7         self.wfile.write(self.data.upper())
 8 if __name__=="__main__":
 9     HOST,PORT="localhost",9999
10     server=SocketServer.TCPServer((HOST,PORT),MyTCPHandler)
11     server.serve_forever()

基本上與上面的相同,但是畢竟StreamRequestHandler是BaseRequestHandler的基類,所以有一些新的方法。

第4行,self.rfile.readline(), self.rfile類型是socket._fileobject,讀寫模式是"rb",方法有:read,readline,readlines,write(data),writelines(list),close,flush
readline()方法會多次調用recv()方法,直到讀取一行;其它的基本類似。

the client side(客戶端)

 1 import socket
 2 import sys
 3 HOST,PORT="localhost",9999
 4 data=" ".join(sys.argv[1:])
 5 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 6 try:
 7     sock.connect((HOST,PORT))
 8     sock.sendall(data+"\n")
 9     received=sock.recv(1024)
10 finally:
11     sock.close()
12 print "Sent:  {}".format(data)
13 print "Received:  {}".format(received)
14 input()

重點:建立一個socket對象sock,socket.SOCK_STREAM說明建立的是一個TCP socket,用socket.SOCK_DGRAM是UDP socket。

sock.connect()方法是與主機建立連接,可見tcp協議是面向連接的可靠地通信協議,這正是tcp與udp協議的不同,udp協議是非面向連接的不可靠的協議,udp發送數據之前並不會與對方建立連接,而是直接發給對方。UDP適用於一次只傳送少量數據、對可靠性要求不高的應用環境。
比如,我們經常使用“ping”命令來測試兩台主機之間TCP/IP通信是否正常,其實“ping”命令的原理就是向對方主機發送UDP數據包,然后對方主機確認收到數據包,如果數據包是否到達的消息及時反饋回來,那么網絡就是通的。例如,在默認狀態下,一次“ping”操作發送4個數據包。大家可以看到,發送的數據包數量是4包,收到的也是4包(因為對方主機收到后會發回一個確認收到的數據包)。這充分說明了UDP協議是面向非連接的協議,沒有建立連接的過程。正因為UDP協議沒有連接的過程,所以它的通信效率高;但也正因為如此,它的可靠性不如TCP協議高。
QQ就使用UDP發消息,因此有時會出現收不到消息的情況。

下面我們就用python來實現UDP的通信協議。

udp服務器端:

 1 import SocketServer
 2 class MyUDPHandler(SocketServer.BaseRequestHandler):
 3     def handle(self):
 4         data=self.request[0].strip()
 5         socket=self.request[1]
 6         print "{} wrote".format(self.client_address[0])
 7         print data
 8         socket.sendto(data.upper(),self.client_address)
 9 if __name__=="__main__":
10     HOST,PORT="localhost",9999
11     server =SocketServer.UDPServer((HOST,PORT),MyUDPHandler)
12     server.serve_forever()

解釋:udp的server與tcp的有一定的區別,它的self.request含有一個data和一個socket,分別用self.request[0]和self.request[1]獲取,由於udp是面向非連接的協議,所以要用sendto()方法,並且要加上客戶端的地址。

udp客戶端:

1 import socket
2 import sys
3 HOST,PORT="localhost",9999
4 data=" ".join(sys.argv[1:])
5 sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
6 sock.sendto(data+"\n",(HOST,PORT))
7 received=sock.recv(1024)
8 print "Sent:  {}".format(data)
9 print "Received:  {}".format(received)

可以看出與tcp的客戶端相比,udp的sock並沒有連接過程,直接發送的數據。

運行,點擊運行服務器端.py的文件,然后在命令行下:python d:/py/client.py hello world  (根據自己的文件地址寫命令)回車就ok了,可以看到客戶端服務器端都有輸出數據。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM