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('/')
def index(info=''):
    net.sock_close()
    return template('index.html', ip=net.local_ip, info=info)

@route('/tcpServ//')
def tcpServ(ip, port):
    if net.sock_open('tcpServ', (ip, port)):
        return template('main.html', title='TCP服务器')
    else:
        redirect('/' + 'TCP服务器开启失败')

@route('/tcpClin//')
def tcpClin(ip, port):
    if net.sock_open('tcpClin', (ip, port)):
        return template('main.html', title='TCP客户端')
    else:
        redirect('/' + '连接到TCP服务器失败')

@route('/udpServ//')
def udpServ(ip, port):
    if net.sock_open('udpServ', (ip, port)):
        return template('main.html', title='UDP服务器')
    else:
        redirect('/' + 'UDP服务器开启失败')

@route('/udpClin//')
def udpClin(ip, port):
    if net.sock_open('udpClin', (ip, port)):
        return template('main.html', title='UDP客户端')
    else:
        redirect('/' + '连接到UDP服务器失败')

@route('/static/')
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的另一种查看方式是在系统偏好设置内,选择共享选项即可,如下图:
python学习--for Mac 问题解决:socket.gaierror: [Errno -2] Name or service not known_第1张图片

添加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,自动接收消息,也可按需发送自定义消息。

你可能感兴趣的:(技术)