【Python】网络编程

1、TCP编程

2、SocketServer模块

3、Twisted框架

4、UDP编程

1、TCP编程——TCP是面向连接的,其一般的设计如下:

# encoding:utf-8
‘‘‘
Created on 2014-6-20

@author: Administrator
‘‘‘

from socket import          socket,          AF_INET,          SOCK_STREAM

import time
import threading

class SockServer(object):
    def __init__(self, port):
        self.HOST = "localhost"
        self.PORT = port
        self.SOCK = (self.HOST, self.PORT)
        self.BUF = 1024
        self._init()

    def _init(self):
        self.sock_server = socket(AF_INET, SOCK_STREAM)
        self.sock_server.bind(self.SOCK)
        self.sock_server.listen(100)

    def __thread_process(self, sock_client, client_addr):
        print "connected :", sock_client.getpeername()

        while True:
            data = sock_client.recv(self.BUF)
            if not data:
                continue
            elif data == "bye":
                print "<< %s" % data
                break
            else:
                sock_client.send(‘[%s] %s‘ % (time.ctime(), data))
                print "%s << %s: %s" % (sock_client.getsockname(), client_addr, data)
        sock_client.close()

    """多线程并发服务器"""
    def process(self):
        while True:
            print "waiting for connection..."
            (sock_client, client_addr) = self.sock_server.accept()
            threading.Thread(target=self.__thread_process, args=(sock_client, client_addr)).start()

    def __del__(self):
        self.sock_server.close()

if __name__ == "__main__":
    port = 12345
    server = SockServer(port)
    server.process()

客户端一般设计:

# encoding:utf-8
‘‘‘
Created on 2014-6-20

@author: Administrator
‘‘‘
from socket import socket, AF_INET, SOCK_STREAM

class SockClient(object):
    def __init__(self, ip, port):
        self.IP = ip
        self.PORT = port
        self.SOCK = (ip, port)
        self.BUF = 1024
        self._init()

    def _init(self):
        self.sock_client = socket(AF_INET, SOCK_STREAM)

    def process(self):
        print "connecting server..."
        self.sock_client.connect(self.SOCK)
        while True:
            data = raw_input(">>")
            self.sock_client.send(data)
            if data.strip() == "bye":
                break
            recv_data = self.sock_client.recv(self.BUF)
            if not recv_data:
                print "no recv!"
            else:
                print recv_data

    def __del__(self):
        self.sock_client.close()

if __name__ == "__main__":
    ip = "localhost"
    port = 12345
    client = SockClient(ip, port)
    client.process()

2、SocketServer模块——用于简化实现网络编程客户端与服务器所需要的大量样板代码。

2.1 创建一个SocketServerTCP服务器:

# encoding:utf-8
‘‘‘
Created on 2014-6-23

@author: Administrator
‘‘‘
from time import ctime
from SocketServer import TCPServer, StreamRequestHandler

"""
    SocketServer 的请求处理器默认行为时接收连接,得到请求,然后关闭连接,这使得我们不能
    在程序运行时,一直保持连接状态,而是每次发送数据到服务器的时候创建一个新的套接字
"""
class MyRequestHandle(StreamRequestHandler):
    """
                客户端有消息发来时,handle函数会被调用
    """
    def handle(self):
        print "...connecting from :", self.client_address
        self.wfile.write(‘[%s] %s‘ % (ctime(), self.rfile.readline()))

if __name__ == "__main__":
    ip = "localhost"
    port = 12345
    tcpServ = TCPServer((ip, port), MyRequestHandle)
    print "waiting for connection..."
    tcpServ.serve_forever()

说明:

1、这里的主要工作是从SocketServer的StreamRequestHandler类派生出一个子类,并重写handle()函数。

在有客户端消息近来的时候,handle()函数就会被调用,如上是一个使用SocketServer模块的回射服务器例子。

2、SocketServer的请求处理器的默认行为时接收连接,得到请求,然后关闭连接,这使得我们不能再程序运行时,一致保持连接状态,

而是每次发送数据到服务器的时候都要创建一个新的套接字。

2.2 创建一个SocketServerTCP客户端:

# encoding:utf-8
‘‘‘
Created on 2014-6-23

@author: Administrator
‘‘‘
from socket import socket, AF_INET, SOCK_STREAM

class SocketClient(object):
    def handle(self, ADDR):
        BUF = 1024
        while True:
            self.client = socket(AF_INET, SOCK_STREAM)
            self.client.connect(ADDR)
            data = raw_input(">>")
            if not data:
                break
            self.client.send("%s\r\n" % data)   #服务端使用的是readline,为了保持一致,发送添加了换行
            rcv_data = self.client.recv(BUF)
            if not rcv_data:
                break
            else:
                print rcv_data.strip()
            self.client.close()

        self.client.close()

if __name__ == "__main__":
    ip = "localhost"
    port = 12345
    client = SocketClient()
    client.handle((ip, port))

说明:

1、本例子是针对使用SocketServer的服务端的例子,其中send()函数需要添加”\r\n”换行符,对应于服务器端的readline()函数

2、发送数据之后,断开连接,因为SocketServer的默认行为使得不能再程序运行时,一致保持连接状态

运行结果:

服务端:

客户端:

3、Twisted框架

简介——Twisted是一个完全事件驱动的网络框架,允许使用和开发完全异步的网络应用程序和协议。

3.1 安装Twisted扩展(Windows)

下载:Twisted和zope

http://twistedmatrix.com/trac/wiki/Downloads

安装Twisted扩展(Linux)

命令:easy_install twisted

eclipse pydev添加twisted模块:

系统已经安装twisted模块,导入twisted,引用其中的方法时,出现如下情况:

解决方法是:

在Eclipse的Window—Preferences—PyDev—Interpreter-Python 窗口下的Forced Buildins添加twisted

即可正常引用twisted包

3.2 Twisted服务端:

# encoding:utf-8
‘‘‘
Created on 2014-6-23

@author: Administrator
‘‘‘

from twisted.internet import reactor, protocol
from time import ctime

"""
    Twisted 是一个完全事件驱动的网络框架,允许使用和开发完全异步的网络应用程序和协议
"""

class TwistedServer(protocol.Protocol):

    """
                    重写connectionMade函数,该函数在有客户端连接时被调用
    """
    def connectionMade(self):
        client = self.client = self.transport.getPeer().host
        print "...connected from ", client, ":", self.transport.getPeer().port

    """
                    该函数在客户端通过网络发送数据过来时被调用
    """
    def dataReceived(self, data):
        self.transport.write("[%s] %s" % (ctime(), data))

if __name__ == "__main__":
    port = 12345
    factory = protocol.Factory()
    factory.protocol = TwistedServer
    print "waiting for connection..."
    reactor.listenTCP(port, factory)
    reactor.run()

说明:

Twistede服务端从Protocol类派生子类,然后重写connectionMade()函数,这个函数在有客户端连接的时候被调用,dataReceived()函数,这个函数在客户端

通过网络发送数据过来的时候被调用,reactor把数据当成参数传到这个函数中

3.3 Twisted客户端

# encoding:utf-8
‘‘‘
Created on 2014-6-23

@author: Administrator
‘‘‘
from twisted.internet import protocol, reactor

class TwistedClient(protocol.Protocol):

    def _senddata(self):
        data = raw_input(">>")
        if data:
            print "...sending %s..." % data
            self.transport.write(data)
        else:
            self.transport.loseConnection()

    #连接建立之后,调用自定义_senddata函数
    def connectionMade(self):
        self._senddata()

    def dataReceived(self, data):
        print data
        self._senddata()

class TClientFactory(protocol.ClientFactory):
    protocol = TwistedClient
    clientConnectionLost = clientConnectionFailed =     lambda self, connector, reason:reactor.stop()

if __name__ == "__main__":
    host = "localhost"
    port = 12345
    reactor.connectTCP(host, port, TClientFactory())
    reactor.run()

说明:

Twisted客户端也从Protocol派生子类,重写connectionMade()和dataReceived()函数,当用户没有任何输入时(参考如上代码中_senddata()函数中else部分),连接结束,结束时,调用loseConnection关闭套接字,这时工厂的clientConnectionLost函数会被调用,同时reactor就被关闭,脚本执行就结束了,由于某些原因,clientConnectionFailed()被调用时,reactor也会被关闭。

4. UDP 编程

UDP是无连接的,服务器一般设计如下:

4.1 服务器端编程

# encoding:utf-8
‘‘‘
Created on 2014-6-20

@author: Administrator
‘‘‘

from socket import         socket,         AF_INET,         SOCK_DGRAM

from time import ctime

class DgramServer(object):
    def __init__(self, port):
        self.HOST = "localhost"
        self.PORT = port
        self.SOCK = (self.HOST, self.PORT)
        self.BUF = 1024
        self._init()

    def _init(self):
        self.dgram_server = socket(AF_INET, SOCK_DGRAM)
        self.dgram_server.bind(self.SOCK)

    def process(self):
        print "waiting for message..."
        while True:
            data, addr = self.dgram_server.recvfrom(self.BUF)
            print "<<",addr, ":%s " % data
            if data == "bye":
                break
            self.dgram_server.sendto("[%s,%s]" % (ctime(), data), addr)

    def __del__(self):
        self.dgram_server.close()

if __name__ == "__main__":
    port = 12345
    dgram = DgramServer(port)
    dgram.process()

注意:

UDP服务端,recvfrom会返回连接的地址

4.2 客户端编程

# encoding:utf-8
‘‘‘
Created on 2014-6-20

@author: Administrator
‘‘‘
from socket import         socket,         AF_INET,         SOCK_DGRAM

class DgramClient(object):
    def __init__(self, ip, port):
        self.HOST = ip
        self.PORT = port
        self.SOCK = (self.HOST, self.PORT)
        self.BUF = 1024
        self._init()

    def _init(self):
        self.dgram_client = socket(AF_INET, SOCK_DGRAM)

    def process(self):
        while True:
            data = raw_input("<<")
            self.dgram_client.sendto(data, self.SOCK)
            if data == "bye":
                    break
            recv_data, dgram = self.dgram_client.recvfrom(self.BUF)
            if not recv_data:
                print "no recv"
            else:
                print ">>", dgram, ":%s" % recv_data

    def __del__(self):
        self.dgram_client.close()

if __name__ == "__main__":
    ip = "localhost"
    port = 12345
    dgram = DgramClient(ip, port)
    dgram.process()

运行结果:

服务端:

客户端1:

客户端2:

【Python】网络编程

时间: 2024-12-05 18:10:06

【Python】网络编程的相关文章

python 网络编程 (二)---tcp

异常 python的socket模块实际上定义了4种可能出现的异常: 1)与一般I/O 和通信问题有关的socket.error; 2)与查询地址信息有关的socket.gaierror; 3)与其他地址错误有关的socket.herror; 4)与在一个socket上调用settimeout()后,处理超时有关的socket.timeout; import socket, sys, time host = sys.argv[1] textport = sys.argv[2] filename

[Python网络编程] DNS缓存解决方案

记得以前写爬虫的时候为了防止dns多次查询,是直接修改/etc/hosts文件的,最近看到一个优美的解决方案,修改后记录如下: import socket _dnscache={} def _setDNSCache(): """ Makes a cached version of socket._getaddrinfo to avoid subsequent DNS requests. """ def _getaddrinfo(*args, **

Python 网络编程

Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法. 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发. 什么是 Socket? Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯. socket()函数 Pyt

[Python网络编程]gevent httpclient以及网页编码

之前看到geventhttpclient这个项目,https://github.com/gwik/geventhttpclient,官方文档说非常快,由于响应使用了C的解析,所以我一直想把这玩意用到项目中, 这两天一直在纠结这玩意,说实在一句话,比较难用,封装的不给力,最大缺陷如下: 1.不支持重定向,重定向需要自己来写,很费事 2.新建的httpclient对象只能发送同域名的请求 这相当的蛋疼,我花了一点时间封装了一下,解决了上面的两个问题,还增加了自动编解码问题,代码如下: #!/usr/

[python] 网络编程之套接字Socket、TCP和UDP通信实例

很早以前研究过C#和C++的网络通信,参考我的文章: C#网络编程之Tcp实现客户端和服务器聊天 C#网络编程之套接字编程基础知识 C#网络编程之使用Socket类Send.Receive方法的同步通讯 Python网络编程也类似.同时最近找工作笔试面试考察Socket套接字.TCP\UDP区别比较多,所以这篇文章主要精简了<Python核心编程(第二版)>第16章内容.内容包括:服务器和客户端架构.套接字Socket.TCP\UDP通信实例和常见笔试考题. 最后希望文章对你有所帮助,如果有不

python 网络编程(五)---DNS域名系统

1.域名系统定义 DNS计算机域名系统由域名服务器和域名解析器组成.通常输入的是网址就是一个域名. 2.域名查询 查询方式包括: 1)正向查询:由域名查找对应的IP(如:119.75.218.77">www.baidu.com->119.75.218.77 ) 2)反向查询:由IP查找域名(如:119.75.218.77 –> www.baidu.com) 查询方式包括: 1)递归查询:当DNS服务器接收到客户端的查询请求时,会做出相应的反应(本地DNS服务器查询.其他服务器查

Python -- 网络编程 -- 抓取网页图片 -- 图虫网

字符串(str)编码成字节码(bytes),字节码解码为字符串 获取当前环境编码:sys.stdin.encoding url编码urllib.parse.quote() url解码urllib.parse.unquote() 列表去重:pages = list(set(pages)) 创建文件夹(可多级创建):os.makedirs(folder)  os.mkdir()只能单级创建 首先分析网页(图虫网)的URL规律: 根网页地址形如: http://tuchong.com/tags/人像/

Python 网络编程(一)

Python 网络编程 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者. socket和file的区别: file模块是针对某个指定文件进行[打开][读写][关闭] socket模块是针对 服务器端 和 客户端Socket 进行[打开][读写][关闭] socket服务端和客户端的网

Python 网络编程(二)

Python 网络编程 上一篇博客介绍了socket的基本概念以及实现了简单的TCP和UDP的客户端.服务器程序,本篇博客主要对socket编程进行更深入的讲解 一.简化版ssh实现 这是一个极其简单的仿ssh的socket程序,实现的功能为客户端发送命令,服务端接收到客户端的命令,然后在服务器上通过subrocess模块执行命令,如果命令执行有误,输出内容为空,则返回"command error"的语句给客户端,否则将命令执行的结果返回给客户端 服务端 1 2 3 4 5 6 7 8

《Python网络编程基础》笔记

主要是关于<Python网络编程笔记>这本书的笔记...可能有点乱... 总共包含6个部分.. 第一部分 第1章:客户/服务器网络介绍 未完待续.....