1. 程式人生 > >python學習--for Mac 問題解決:socket.gaierror: [Errno -2] Name or service not known

python學習--for Mac 問題解決:socket.gaierror: [Errno -2] Name or service not known

在Mac電腦上利用bottle搭建簡單web伺服器,以實現mac版本的網路除錯助手。

主程式從csdn下載,下載地址為:http://download.csdn.net/detail/yuanhuamanjing/9383142,推測為win執行環境。除錯後的伺服器程式main.py如下:

#-*-coding:utf8;-*-
#qpy:2
#qpy:webapp:TCPUDP 
#qpy://localhost:8081/

import sys, os, re, json
import socket, threading, time, Queue

from bottle import
route, run, redirect from bottle import static_file, template if True: #Android QPython os.chdir(os.path.dirname(__file__)) sys.path.append('/data/data/com.hipipal.qpyplus/files/lib/python2.7/site-packages/websocket_server-0.4-py2.7.egg') sys.path.append('/data/data/com.hipipal.qpyplus/files/lib/python2.7/site-packages/CherryPy-3.8.0-py2.7.egg'
) @route('/') @route('/<info>') def index(info=''): net.sock_close() return template('index.html', ip=net.local_ip, info=info) @route('/tcpServ/<ip>/<port:int>') def tcpServ(ip, port): if net.sock_open('tcpServ', (ip, port)): return template('main.html', title='TCP伺服器'
) else: redirect('/' + 'TCP伺服器開啟失敗') @route('/tcpClin/<ip>/<port:int>') def tcpClin(ip, port): if net.sock_open('tcpClin', (ip, port)): return template('main.html', title='TCP客戶端') else: redirect('/' + '連線到TCP伺服器失敗') @route('/udpServ/<ip>/<port:int>') def udpServ(ip, port): if net.sock_open('udpServ', (ip, port)): return template('main.html', title='UDP伺服器') else: redirect('/' + 'UDP伺服器開啟失敗') @route('/udpClin/<ip>/<port:int>') def udpClin(ip, port): if net.sock_open('udpClin', (ip, port)): return template('main.html', title='UDP客戶端') else: redirect('/' + '連線到UDP伺服器失敗') @route('/static/<filepath:path>') def server_static(filepath): return static_file(filepath, root='./static/') @route('/__exit') def __exit(): threading.Thread(target=websocketServer.server.shutdown).start() class TCPUDP(object): def __init__(self): self.local_ip = socket.gethostbyname(socket.gethostname()) self.hexShow = False self.hexSend = False threading.Thread(target=self.sock_recv).start() threading.Thread(target=self.sock_listen).start() def sock_open(self, mode, addr): self.mode, self.addr = mode, addr if self.mode == 'tcpServ': self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: self.sock.bind(addr) self.sock.listen(10) except Exception: return False else: return True elif self.mode == 'tcpClin': self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: self.sock.connect(addr) except Exception: return False else: return True elif self.mode == 'udpServ': self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: self.sock.bind(addr) except Exception: return False else: return True elif self.mode == 'udpClin': self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) return True def sock_send(self, str): map = json.loads(str) if map['type'] == 'cmd': if map.has_key('hexShow'): self.hexShow = map['hexShow'] elif map.has_key('hexSend'): self.hexSend = map['hexSend'] else: str = map['data'] if self.mode == 'tcpServ': if hasattr(self, 'clinSock'): self.clinSock.send(str) elif self.mode == 'tcpClin': self.sock.send(str) elif self.mode == 'udpServ': if hasattr(self, 'clinAddr'): self.sock.sendto(str, self.clinAddr) elif self.mode == 'udpClin': self.sock.sendto(str, self.addr) def sock_recv(self): while True: try: if self.mode == 'tcpServ': self.clinSock.setblocking(False) data = self.clinSock.recv(1024) elif self.mode == 'tcpClin': self.sock.setblocking(False) data = self.sock.recv(1024) elif self.mode == 'udpServ': self.sock.setblocking(False) data, addr = self.sock.recvfrom(1024) elif self.mode == 'udpClin': self.sock.setblocking(False) data, addr = self.sock.recvfrom(1024) except Exception as ex: pass else: if self.mode == 'udpServ': self.clinAddr = addr print data if hasattr(websocketServer, 'client'): websocketServer.send_message(data) time.sleep(0.1) def sock_close(self): try: self.sock.shutdown(socket.SHUT_RDWR) except Exception: pass try: self.sock.close() except Exception: pass if hasattr(self, 'clinSock'): delattr(self, 'clinSock') if hasattr(self, 'clinAddr'): delattr(self, 'clinAddr') def sock_listen(self): while 1: try: sock, addr = self.sock.accept() except Exception: pass else: self.clinSock = sock time.sleep(5) class WebsocketServer(object): def __init__(self): import websocket_server self.server = websocket_server.WebsocketServer(13254) self.server.set_fn_new_client(self.websocket_new_client) self.server.set_fn_message_received(self.message_received) threading.Thread(target=self.server.run_forever).start() def websocket_new_client(self, client, server): self.client = client def message_received(self, client, server, message): net.sock_send(message) def send_message(self, msg): self.server.send_message(self.client, msg) if __name__ == '__main__': net = TCPUDP() websocketServer = WebsocketServer() #建立socket run(host='localhost', port='8081', debug=True) #啟動本地net assistant

執行時“socket.gethostbyname(socket.gethostname())“語句報錯,提示:“socket.gaierror: [Errno -8] Name or service not known”。百度後發現針對mac電腦的問題解答很少,參考網頁連結http://www.th7.cn/Program/Python/201605/865623.shtml,原文內容摘抄如下:

該錯誤的原因是/etc/hostname檔案寫的hostname 沒有寫在/etc/hosts裡, 加上就好了 。 比如新增 “127.0.0.1 myname” 到hosts最後一行, 即可。

socket.gethostname()讀取/etc/hostname中的name; socket.gethostbyname(name)是通過name來提取/etc/hosts裡和name對應的ip 。如果hosts裡沒有對應的name,肯定就要丟擲錯誤。

因此前往/etc資料夾,發現本機無hostname檔案,有hosts檔案。將hosts檔案備份(重要事情說三遍:務必牢記修改系統檔案前必須備份,以免發生意外!務必牢記修改系統檔案前必須備份,以免發生意外!務必牢記修改系統檔案前必須備份,以免發生意外!)開啟新的hosts檔案,發現hosts檔案內容僅有一行localhost記錄:

127.0.0.1 localhost

在終端內開啟python模式,利用如下程式碼查詢本機hostname,這裡舉例為“xxMacBookPro.local”:

import socket
socket.gethostname()

注:本機hostname的另一種檢視方式是在系統偏好設定內,選擇共享選項即可,如下圖:
在系統偏好設定內檢視hostname

新增hosts檔案內容如下:

127.0.0.1 localhost
127.0.0.1 xxMacBookPro.local
127.0.0.1 xxMacBookPro

再此執行程式即可成功啟動web伺服器。

附修改後的執行檔案(去除bootstrap.min.css等內容,提高網頁載入速度),下載地址為http://download.csdn.net/detail/qiaokelinaicha/9803586
1. main.py
2. index.html
3. main.html

檔案執行順序為:
1.執行main.py,啟動本地web伺服器,主頁地址為http://localhost:8081/,網頁自動跳轉至index.html;
2.選擇相應的執行模式,tcp伺服器模式時輸入本機伺服器ip地址和埠號;tcp客戶端模式時輸入監聽伺服器ip地址和埠號;udp模式與tcp模式對應。選擇“開始監聽”按鈕併成功建立socket後,網頁跳轉至main.html,自動接收訊息,也可按需傳送自定義訊息。