2016-04-29 52 views
0

我想確定一個web服務器列表是否正在偵聽與套接字庫的端口。不過,我無法通過列表成功運行迭代:無法迭代字符串列表連接功能與套接字

#!/usr/bin/python 

    import socket 

    myList = ['www.google.com', 'www.spoon.com'] 
    scanList = [] 
    port = 80 

    def resolveHost(x): 
     try: 
      h = socket.gethostbyname(x) 
     except: 
      pass 
     return h 

    def scan(host,port): 
     s = socket.socket() 
     s.connect(host,port) 
     print s.recv(3) 


    for x in myList: 
     scanList.append(resolveHost(x)) 

    print scanList 

    for x in scanList: 
     scan(x,25) 


This is returning: 

    Traceback (most recent call last): 
    ['216.58.199.196', '207.32.184.61'] 
     File "C:/Users/Casey/Desktop/projects/dsid_check.py", line 28, in <module> 
     scan(x,25) 
     File "C:/Users/Casey/Desktop/projects/dsid_check.py", line 18, in scan 
     s.connect(host,port) 
     File "C:\Python27\lib\socket.py", line 228, in meth 
     return getattr(self._sock,name)(*args) 
    TypeError: connect() takes exactly one argument (2 given) 

    Process finished with exit code 1 

我希望看到的是來自這些頁面的響應,但我沒有。

編輯---------- ------------來源

所以我修改我的源看成這樣:

#!/usr/bin/python 

import socket 

myList = ['www.espn.com', 'www.google.com', 'www.spoon.com'] 

scanList = [] 
port = 80 

def resolveHost(x): 
    try: 
     h = socket.gethostbyname(x) 
     return h 
    except: 
     print "Could not resolve %s" % x 

def scan(host,port): 
    hostR = resolveHost(host) 
    s = socket.socket() 
    s.settimeout(3) 
    s.connect((hostR,port)) 
    try: 
     print s.recv(1024) 
    except: 
     print "Connection to %s timed out" % x 


for x in myList: 
    scanList.append(resolveHost(x)) 

for x in scanList: 
    scan(x,port) 

有了這個,我無法連接到應該在線的Web服務器列表。現在閱讀Alex推薦的圖書館鏈接。

+0

假設'socket.gethostbyname'提高你忽略一個例外。如何在沒有定義時返回'h'?讓例外提出。 –

+0

您還可以將'scanList'定義爲'[在myList中爲x的resolveHost(x)]'或'map(resolveHost,myList)'。 –

回答

0

您需要在一個元組中將兩個參數作爲一對傳遞。

>>> import socket 
>>> s = socket.socket() 
>>> help(s.connect) 

connect(...) method of socket._socketobject instance 
    connect(address) 

    Connect the socket to a remote address. For IP sockets, the address 
    is a pair (host, port). 

>>> s.connect('127.0.0.1', 80) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Users/alexhall/.pyenv/versions/2.7.10/lib/python2.7/socket.py", line 228, in meth 
    return getattr(self._sock,name)(*args) 
TypeError: connect() takes exactly one argument (2 given) 
>>> s.connect(('127.0.0.1', 80)) # works 
+0

所以我假設.s.connect()所需的輸入需要兩個輸入。所以一個元組被視爲一個單一的輸入? –

+0

@CaseyMcCarthy它完全沒有意義的設計,但是這就是方法,是的。 –

+0

@CaseyMcCarthy順便說一句,這似乎並不奏效,因爲s.recv(3)會永遠阻塞。在HTTP中,客戶端需要發送適當的請求,服務器不會在連接時發送數據。嘗試請求庫:http://docs.python-requests.org/en/master/user/quickstart/ –

0

通過Alex的建議後,我能夠擴展我以前想做的事情。請參閱這個作爲原始源代碼的完整示例。

#!/usr/bin/python 

import socket, urllib2 

httpList = ['www.espn.com', 'www.google.com', 'www.spoon.com'] 
smtpList = ['smtp.gmail.com', 'aspmx.l.google.com'] 
scanHttp = [] 
scanSmtp = [] 

def resolveHost(x): 
    try: 
     h = socket.gethostbyname(x) 
     print "Resolved %s to %s" % (x, h) 
     return h 
    except: 
     print "Could not resolve %s" % x 

def scan(host,port): 
    hostR = socket.gethostbyname(host)#resolveHost(host) 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    s.settimeout(3) 
    s.connect((hostR,port)) 
    try: 
     if (port == 80): 
      r = urllib2.urlopen('http://'+str(host)).read() 
      if 'DOCTYPE' in r: 
       print "%s is up" % host 
      elif 'doctype' in r: 
       print "%s is up" % host 
     elif (port == 25): 
      r = s.recv(1024) 
      if '220' in r: 
       print "%s is up" % host 
    except: 
     print "Connection to %s timed out" % x 


for x in httpList: 
    scan(x,80) 

for x in smtpList: 
    scan(x,25) 

這將產生檢查的預期結果是兩個列表可達在選擇端口:

C:\Python27\python.exe C:/Users/Casey/Desktop/projects/service_check.py 
www.espn.com is up 
www.google.com is up 
www.spoon.com is up 
smtp.gmail.com is up 
aspmx.l.google.com is up 

Process finished with exit code 0 
+0

太棒了!既然你設置了超時時間,我假設你明白我的意思是永遠阻止。你可以做一些小的改進:(1)'resolveHost'更好,但是仍然沒有理由隱藏異常。將'raise'加到最後,它會被重新拋出,以便在出現錯誤時可以看到方便的回溯。 (2)Python不需要條件附近的東西,你可以寫'if port == 80:'。 (3)你寫了''http://'str(主機)',但是我們確實知道'host'是一個字符串?如果不是你有更大的問題,這不會解決它們。 –

+0

(4)考慮'r'或'doctype'中的'if'DOCTYPE'在r:print ...中以減少重複,甚至更好:'if'DOCTYPE'in r.upper()'。 (5)這實際上非常重要:養成良好,有意義的名字。特別避免單個字母的名稱。 'hostR'是什麼意思?答案並不重要,因爲你不應該解釋它,它應該是顯而易見的。 (6)如果港口既不是80也不是25港口,你想做什麼?考慮打印消息或引發異常,以便在輸入錯誤的端口時更容易發現問題。 –

+0

(7)避免廣泛的異常捕獲,例如,除了「except:」或「except:Exception」:如果可能的話。他們捕捉太多的錯誤,你可能不想捕捉。現在,如果達到了這個程度,你實際上並不知道問題是暫停。考慮一些更具體的東西,比如'除了socket.error:'。再次重新審視異常以查看回溯,以便查看超時的位置很有用。 (8)對'doctype'的測試可能不夠普遍。試着看看'gmail.com'發生了什麼。你可能想檢查狀態碼是在200到499之間。 –