chapter 16 网络编程

 

套接字:通信端点
什么是套接字?python

书上说的端口是数据结构和I/O缓存区”是指硬件端口,网络编程里的端口能够理解为应用程序的ID。编程

说得形象点,套接字就相似咱们人类的门
咱们打开门,经过门外面的人能够进来
咱们推开门,里面的人也能够出去
一样,外面的数据能够经过socket把它存储在本地机器的缓冲区里等待本地机器接收
本地机器的数据能够经过socket放在缓冲区里等待发送到对方机器上
当咱们把门给关上时,就拒绝了和外面世界的交往。缓存


套接字是一种具备以前所说的“通信端点”概念的计算机网络数据结构。网络化的应用程序在开始任何通安全

讯以前都必须要建立套接字。就像电话的插口同样,没有它就彻底没办法通信。
套接字有两种,分别是基于文件型的和基于网络型的。
基于文件型的:
Unix 套接字是咱们要介绍的第一个套接字家族。其“家族名”为AF_UNIX,因为两个进程都运行在同一台服务器

机器上,并且这些套接字是基于文件的。因此,它们的底层结构是由文件系统来支持的。这样作至关有道网络

理,由于,同一台电脑上,文件系统的确是不一样的进程都能访问的。数据结构

基于网络型的
它有本身的家族名字:AF_INET,或叫“地址家族:Internet”。框架

Python 只支持AF_UNIX,AF_NETLINK,和AF_INET 家族。因为咱们只关心网络编程,因此在本章的大部分异步

时候,咱们都只用AF_INET。socket

套接字的类型只有两种。一种是面向链接的套接字,即在通信以前必定要创建一条链接,就像跟朋友打电

话时那样。这种通信方式也被称为“虚电路”或“流套接字”。面向链接的通信方式提供了顺序的,可靠

的,不会重复的数据传输,并且也不会被加上数据边界。这也意味着,每个要发送的信息,可能会被拆

分红多份,每一份都会很少很多地正确到达目的地。而后被从新按顺序拼装起来,传给正在等待的应用程

序。


建立套接字:
from socket import *

tcpsock=socket(AF_INET,SOCK_STREAM)
udpsock=socket(AF_INET,SOCK_DGRAM)


套接字对象(内建)方法

函数 描述
服务器端套接字函数
s.bind() 绑定地址(主机,端口号对)到套接字
s.listen() 开始TCP 监听
s.accept() 被动接受TCP 客户的链接,(阻塞式)等待链接的到来
客户端套接字函数
s.connect() 主动初始化TCP 服务器链接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛异常
公共用途的套接字函数
s.recv() 接收TCP 数据
s.send() 发送TCP 数据
s.sendall() 完整发送TCP 数据
s.recvfrom() 接收UDP 数据
s.sendto() 发送UDP 数据
s.getpeername() 链接到当前套接字的远端的地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回指定套接字的参数
s.setsockopt() 设置指定套接字的参数
s.close() 关闭套接字

Blocking-Oriented Socket Methods
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout()       设置阻塞套接字操做的超时时间
s.gettimeout()    获得阻塞套接字操做的超时时间
面向文件的套接字的函数
s.fileno() 套接字的文件描述符
s.makefile() 建立一个与该套接字关连的文件

 

 

 建立一个tcp服务器的伪代码:
ss=socket()  #建立服务器套接字
ss.bind()    #把地址绑定到套接字上
ss.listen()  #监听连接
inf_loop     #服务器无线循环
cs=ss.accept()    #接受客户的连接
comm_loop           #通信循环
cs.recv()/cs.send()    #对话(接受与发送)
cs.close()           #关闭客户套接字
ss.close()           #关闭服务器套接字(可选)


会建立一个TCP 服务器程序:

from socket import *
from time import ctime

HOST=''
PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)

tcpSerSock=socket(AF_INET,SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)


while True:
    print 'waiting for connection...'
    tcpCliSock,addr=tcpSerSock.accept()
    print '... connected from:',addr

    while True:
        data=tcpCliSock.rece(BUFSIZ)
        if not data:
            break
        tcpCliSock.send('[%s]%s'%(ctime(),data))

    tcpCliSock.close()
tcpSerSock.close()


建立TCP 客户端:

伪代码:
cs = socket() # 建立客户套接字
cs.connect() # 尝试链接服务器
comm_loop: # 通信循环
cs.send()/cs.recv() # 对话(发送/接收)
cs.close() # 关闭客户套接字

实例:
from socket import *
from time import ctime,sleep

HOST='localhost'

PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)

tcpCliSock=socket(AF_INET,SOCK_STREAM)

tcpCliSock.connect(ADDR)

while True:
    data=raw_input('>')
    if not data:
        break

    tcpCliSock.send(data)
    sleep(6)
    data=tcpCliSock.recv(BUFSIZ)
    if not data:
        break
    print data
tcpCliSock.close()

运行咱们的客户端与服务器程序,先运行服务器端再运行客户端,由于服务器端是被动的,他要在那里等

待着。

socket.error: [Errno 10054]说明服务器端出现了error,socket.error: [Errno 10053]客户端出现了问


建立一个UDP 服务器:


ss = socket() # 建立一个服务器套接字
ss.bind() # 绑定服务器套接字
inf_loop: # 服务器无限循环
cs = ss.recvfrom()/ss.sendto() # 对话(接收与发送)
ss.close() # 关闭服务器套接字


实例:
from socket import *
from time import ctime,sleep

HOST='localhost'

PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)

tcpCliSock=socket(AF_INET,SOCK_STREAM)

tcpCliSock.connect(ADDR)

while True:
    data=raw_input('>')
    if not data:
        break

    tcpCliSock.send(data)
    sleep(6)
    data=tcpCliSock.recv(BUFSIZ)
    if not data:
        break
    print data
tcpCliSock.close()

建立一个UDP 客户端:
伪代码:
cs = socket() # 建立客户套接字
comm_loop: # 通信循环
cs.sendto()/cs.recvfrom() # 对话(发送/接收)
cs.close() # 关闭客户套接字

实例:
from socket import *

HOST='localhost'
PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)

udpCliSock=socket(AF_INET,SOCK_DGRAM)

while True:
    data=raw_input('>')
    if not data:
        break
    udpCliSock.sendto(data,ADDR)
    data,ADDR=udpCliSock.recvfrom(BUFSIZ)

    if not data:
        break

    print data
udpCliSock.close

套接字模块属性:
属性名字 描述
数据属性
AF_UNIX, AF_INET, AF_INET6a Python 支持的套接字家族
SO_STREAM, SO_DGRAM 套接字类型 (TCP = 流, UDP = 数据报)
has_ipv6b 表示是否支持IPv6 的标志变量
异常
error 套接字相关错误
herrora 主机和地址相关的错误
gaierrora 地址相关的错误
timeoutb 超时
函数
socket() 用指定的地址家族,套接字类型和协议类型(可选)建立一个套接字对象
socketpair()c 用指定的地址家族,套接字类型和协议类型(可选)建立一对套接字对象
fromfd() 用一个已经打开的文件描述符建立一个套接字对象数据属性
ssl()d 在套接字初始化一个安全套接字层(SSL)。不作证书验证。
getaddrinfo()a 获得地址信息
getfqdn()e 返回完整的域的名字
gethostname() 获得当前主机名

gethostbyname() 由主机名获得对应的ip 地址
gethostbyname_ex() gethostbyname()的扩展版本,返回主机名,主机全部的别名和
IP 地址列表。
gethostbyaddr() 由IP 地址获得DNS 信息,返回一个相似gethostbyname_ex()
的3 元组。
getprotobyname() 由协议名(如'tcp')获得对应的号码。
getservbyname()/ 由服务名获得对应的端口号或相反
getservbyport() 两个函数中,协议名都是可选的。
ntohl()/ntohs() 把一个整数由网络字节序转为主机字节序
htonl()/htons() 把一个整数由主机字节序转为网络字节序
inet_aton()/ 把IP 地址转为32 位整型,以及反向函数。(仅对IPv4 地址有效)
inet_ntoa()
inet_pton()/ 把IP 地址转为二进制格式以及反向函数。(仅对IPv4 地址有效)
inet_ntop()b
getdefaulttimeout()/ 获得/设置默认的套接字超时时间,单位秒(浮点数)
setdefaulttimeout()

 

*SocketServer 模块

用*SocketServer 模块简化上面的例子:
tcp server:
from SocketServer import TCPServer as TCP, StreamRequestHandler as SRH
from time import ctime

HOST=''
PORT=21567
ADDR=(HOST,PORT)

class MyRequestHandler(SRH):
    def handle(self):
        print '...connected from:',self.client_address
        self.wfile.write('[%s]%s'%(ctime(),self.rfile.readline()))

tcpServ=TCP(ADDR,MyRequestHandler)
print 'waiting for connection...'
tcpServ.serve_forever()


tcp client:

from socket import *
from time import ctime,sleep

HOST='localhost'

 核心编程

PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)

 

while True:
    tcpCliSock=socket(AF_INET,SOCK_STREAM)
    tcpCliSock.connect(ADDR)
    data=raw_input('>')
    if not data:
        break

    tcpCliSock.send('%s\r\n'%data)

    data=tcpCliSock.recv(BUFSIZ)
    if not data:
        break
    print data.strip()
    tcpCliSock.close()

Twisted 框架介绍:Twisted 是一个彻底事件驱动的网络框架。它容许你使用和开发彻底异步的网络应用程序和协议。这个模块要单独安装,内容也比较多,稍后再仔细研究吧

相关文章
相关标签/搜索