網絡通信的基本接口是socket,它擴展了操作系統的基本I/O到網絡網絡通信。socket可以通過socket()函數來建立,通過connect()函數來連接。得到了socket,可以確定本地和遠程端點的IP地址和端口號。socket對不同的協議來說都是一種通用的接口,它可以處理TCP和UDP通信。
建立socket需要兩步:建立socket對象、連接到遠程服務器上
import socket print "Creating socket" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #指明通信類型和協議家族 print "Done!" print "Connecting to remote host..." s.connect(("www.baidu.com", 80)) print "Done"
運行結果
Creating socket Done! Connecting to remote host... Done
查找端口號
通過協議名和端口名查找端口號(unix系統可以在etc/services中找到對應的端口號)
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 port print "done!" print "Connecting to remote host..." s.connect(("www.baidu.com", port)) print "Done!!"
運行結果
Creating socket Done! Looking up port number... 80 done! Connecting to remote host... Done!!
從socket獲得信息
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 port print "done!" print "Connecting to remote host..." s.connect(("www.baidu.com", port)) print "Done!!" print "Connected from", s.getsockname() #獲得本地機器的ip和端口號(端口號由操作系統隨機分配,每次都不一樣) print "Connected to", s.getpeername() #獲得連接機器的ip和端口號
一次運行結果
Creating socket
Done!
Looking up port number...
80
done!
Connecting to remote host...
Done!!
Connected from ('192.168.209.129', 56245)
Connected to ('220.181.112.244', 80)
利用socket通信
socket對象:send()、sendto()、recv()、recvfrom()
文件類對象:read()、write()、readline()
處理錯誤
import socket, sys host = sys.argv[1] textport = sys.argv[2] filename = sys.argv[3] try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, e: print "Strange error creating socket: %s" % e sys.exit(1) try: port = int(textport) except ValueError: try: port = socket.getservbyname(textport, 'tcp') except socket.error, e: print "Couldn't find your port: %s" % e sys.exit(1) try: s.connect((host, port)) except socket.gaierror, e: print "Address-related error connecting to server: %s" %e sys.exit(1) except socket.error, e: print "Connection error: %s" %e sys.exit(1) try: s.sendall("GET %s HTTP/1.0\r\n\r\n" % filename) except socket.error, e: print "Error sending data: %s" %e sys.exit(1) print "---------------------------------------" while 1: try: buf = s.recv(2048) except socket.error, e: print "========Error receving data: %s=======" %e sys.exit(1) if not len(buf): break sys.stdout.write(buf) print "---------------------------------------"
改進
#coding: utf-8 import socket import sys import time host = sys.argv[1] textport = sys.argv[2] filename = sys.argv[3] try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, e: print "Strange error creating socket: %s" % e sys.exit(1) try: port = int(textport) except ValueError: print "ValueError" try: port = socket.getservbyname(textport, 'tcp') except socket.error, e: print "Couldn't find your port: %s" % e sys.exit(1) try: s.connect((host, port)) except socket.gaierror, e: #主機名不對 print "Address-related error connecting to server: %s" %e sys.exit(1) except socket.error, e: #連接遠程主機有問題 print "Connection error: %s" %e sys.exit(1) print "Sleepping........." time.sleep(10) print "Continuing." try: s.sendall("GET %s HTTP/1.0\r\n\r\n" % filename) except socket.error, e: print "Error sending data: %s" % e sys.exit(1) try: s.shutdown(1) except socket.error, e: print "Error sending data (detected by shutdown):%s" % e sys.exit(1) print "---------------------------------------" while 1: try: buf = s.recv(2048) print "try" except socket.error, e: print "========Error receving data: %s=======" %e sys.exit(1) if not len(buf): #接受的為空 print "breaK" break sys.stdout.write(buf) print "---------------------------------------"
