Python伺服器開發知識摘要
1用MySQLdb模組操作MySQL資料庫非常方便。示例程式碼如下:
import os, sys import MySQLdb try: conn MySQLdb.connect(host=’localhost’,user=’root’,passwd=’’,db=’address’ except Exception,e: print e sys.exit() cursor=conn.cursor() sql=’insert into address(name, address) values(%s, %s)’ value=((“zhangsan”,”haidian”),(“lisi”,”haidian”)) try cursor.executemany(sql,values) except Exception, e: print e sql=”select * from address” cursor.execute(sql) data=cursor.fetchall() if data for x in data: print x[0],x[1] cursor.close() conn.close()
2、網路基礎
1)利用Socket建立網路連線的步驟:
建立Socket連線至少需要一對套接字,其中一個運行於客戶端,稱為ClientSocket ,另一個運行於伺服器端,稱為ServerSocket 。
套接字之間的連線過程分為三個步驟:伺服器監聽,客戶端請求,連線確認。
1。伺服器監聽:伺服器端套接字並不定位具體的客戶端套接字,而是處於等待連線的狀態,實時監控網路狀態,等待客戶端的連線請求。
2。客戶端請求:指客戶端的套接字提出連線請求,要連線的目標是伺服器端的套接字。為此,客戶端的套接字必須首先描述它要連線的伺服器的套接字,指出伺服器端套接字的地址和埠號,然後就向伺服器端套接字提出連線請求。
3。連線確認:當伺服器端套接字監聽到或者說接收到客戶端套接字的連線請求時,就響應客戶端套接字的請求,建立一個新的執行緒,把伺服器端套接字的描述發給客戶端,一旦客戶端確認了此描述,雙方就正式建立連線。而伺服器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連線請求。
2)HTTP連結的特點
HTTP協議即超文字傳送協議(Hypertext Transfer Protocol ),是Web聯網的基礎,也是手機聯網常用的協議之一,HTTP協議是建立在TCP協議之上的一種應用。
HTTP連線最顯著的特點是客戶端傳送的每次請求都需要伺服器回送響應,在請求結束後,會主動釋放連線。從建立連線到關閉連線的過程稱為“一次連線”。
3)Python網路程式設計
3.1)Python提供了訪問底層作業系統Socket介面的全部方法,還提供了一組加密和認證通訊的服務,SSL/TLS。
Sockets其實是一個檔案描述符,不同於不同於本地檔案,它連線了網路上的一個檔案。
a)、建立一個UDP 本地連線:
#!/usr/bin/env python import socket, sys s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) MAX = 65535 PORT = 1060 if sys.argv[1:] == ['server']: s.bind(('127.0.0.1', PORT)) print 'Listening at', s.getsockname() while True: data, address = s.recvfrom(MAX) print 'The client at', address, 'says', repr(data) s.sendto('Your data was %d bytes' % len(data), address) elif sys.argv[1:] == ['client']: print 'Address before sending:', s.getsockname() s.sendto('This is my message', ('127.0.0.1', PORT)) print 'Address after sending', s.getsockname() data, address = s.recvfrom(MAX) # overly promiscuous - see text! print 'The server', address, 'says', repr(data) else: print >>sys.stderr, 'usage: udp_local.py server|client'
b)執行這段程式碼:
python filename.py server #Listening at ('127.0.0.1', 1060) #Address before sending: ('0.0.0.0', 0) #Address after sending ('0.0.0.0', 62892) #The server ('127.0.0.1', 1060) says 'Your data was 18 bytes' python filename.py client #The client at ('127.0.0.1', 62892) says 'This is my message'
3.2)、建立遠端連線並驗證收到的資訊:
import random, socket, sys s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) MAX = 65535 PORT = 1060 if 2 <= len(sys.argv) <= 3 and sys.argv[1] == 'server': interface = sys.argv[2] if len(sys.argv) > 2 else '' s.bind((interface, PORT)) print 'Listening at', s.getsockname() while True: data, address = s.recvfrom(MAX) if random.randint(0, 1): print 'The client at', address, 'says:', repr(data) s.sendto('Your data was %d bytes' % len(data), address) else: print 'Pretending to drop packet from', address elif len(sys.argv) == 3 and sys.argv[1] == 'client': hostname = sys.argv[2] s.connect((hostname, PORT)) print 'Client socket name is', s.getsockname() delay = 0.1 while True: s.send('This is another message') print 'Waiting up to', delay, 'seconds for a reply' s.settimeout(delay) try: data = s.recv(MAX) except socket.timeout: delay *= 2 # wait even longer for the next request if delay > 2.0: raise RuntimeError('I think the server is down') else: break # we are done, and can stop looping print 'The server says', repr(data) else: print >>sys.stderr, 'usage: udp_remote.py server [ <interface> ]' print >>sys.stderr, ' or: udp_remote.py client <host>' sys.exit(2)
這裡的s.connect((hostname, PORT))方法,可以讓我們不用每次都呼叫s.sendto('This is my message', ('127.0.0.1', PORT))。直接呼叫
s.send('This is another message')。
3.3)SOCKET
socket是作業系統中I/O的延續,它可以使程序和機器之間的通訊成為可能。socket可以看成一個標準的檔案描述符。不同的是檔案需要用open()函式開啟,而socket用socket()
函式建立.recv()、send()函式和read()、write()函式極為相似。
TCP一般通過accept()來為每個連線的客戶端建立一個新的scoket。UDP一般只是使用一個單一的socket,完全依靠recvfrom()返回的值來判斷該往哪裡傳送響應。
客戶端:
1、建立一個socket:
//SOCK_STREAM表示TCP,SOCK_DGRAM表示UDP,AF_INET表示IPv4
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
2、連線socket
連線socket需要一個tuple引數,來提供IP和埠號:
s.connect((“www.example.com”, 80))
3、
#!/usr/bin/env python import socket print "Creating socket...", s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print "done." print "Looking up port number...", port = socket.getservbyname('http', 'tcp') print "done." print "Connecting to remote host on port %d..." % port, s.connect(("www.google.com", port)) print "done." #獲取本身的IP和埠號 print "Connected from", s.getsockname() #獲取遠端的IP和埠號 print "Connected to", s.getpeername()
檔案類物件:
import socket, sys port = 70 host = sys.argv[1] filename = sys.argv[2] s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) fd = s.makefile('rw', 0) fd.write(filename + "\r\n") for line in fd.readlines(): sys.stdout.write(line)
高階介面:
import urllib, sys f = urllib.urlopen(sys.argv[1]) while 1: buf = f.read(2048) if not len(buf): break sys.stdout.write(buf)
伺服器端:
1、建立一個連線:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
2、設定socket選項:
//socket 埠可立即複用
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
3、繫結socket:
s.bind((host, port))
4、監聽:
s.listen(1)
5、接受連線:
while 1: clientsock, clientaddr = s.accept() print "Got connection from", clientsock.getpeername() clientsock.close()
6、
#!/usr/bin/env python import socket, traceback host = '' # Bind to all interfaces port = 51423 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, port)) #這裡設定每次最多隻有一個等候處理的請求,真正的伺服器會設定一個很高的數字。 s.listen(1) while 1: try: clientsock, clientaddr = s.accept() except KeyboardInterrupt: raise except: traceback.print_exc() continue # Process the connection try: print "Got connection from", clientsock.getpeername() # Process the request here except (KeyboardInterrupt, SystemExit): raise except: traceback.print_exc() # Close the connection try: clientsock.close() except KeyboardInterrupt: raise except: traceback.print_exc()
使用UDP:
#!/usr/bin/env python import socket, traceback host = '' # Bind to all interfaces port = 51423 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, port)) while 1: try: message, address = s.recvfrom(8192) print "Got data from", address # Echo it back s.sendto(message, address) except (KeyboardInterrupt, SystemExit): raise except: traceback.print_exc()