Chinaunix首页 | 论坛 | 博客
  • 博客访问: 450335
  • 博文数量: 112
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1085
  • 用 户 组: 普通用户
  • 注册时间: 2013-01-15 09:42
个人简介

上善若水,不浮不沉!

文章存档

2021年(2)

2020年(3)

2018年(2)

2017年(1)

2016年(8)

2015年(11)

2014年(57)

2013年(28)

我的朋友

分类: LINUX

2014-02-28 17:06:00

--------------------------------------------------------------------------
#一个停止并等待输入或输出的程序成为被阻塞的程序
#死锁问题,在每次发送数据时接收端都接受一次,避免数据积压
--------------------------------------------------------------------------
基本客户端操作
--------------------------------------------------------------------------
#文件对象类型:read()、write()、readline()、readlines(),[↓阻塞与非阻塞]
#send()[TCP]、sendall()[TCP]、sendto()[UDP]、recv()[TCP]、recvfrom()[UDP]
#一旦结束写操作,应该立刻调用shutdown()函数,强制清除缓存里面的内容
--------------------------------------------------------------------------
#通信类型AF_INET(IPv4),协议簇SOCK_STREAM(TCP),SOCK_DGRAM(UDP)
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  #建立SOCKET
s.connect(('quux.org', 70))                           #连接服务器及端口
s.sendall("/ \r\n")                                   #发送全部数据
s.send("/ \r\n")                                      #发送数据(可循环)
buf = s.recv(2048)                                    #接收数据(可循环)
--------------------------------------------------------------------------
文件类对象
--------------------------------------------------------------------------
#对于makefile()指定缓冲器需要使用flush()清理缓冲内容
#对于makefile()返回的对象并不提供一个对shutdown()的调用
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)     #建立SOCKET
s.connect(('quux.org', 70))                              #连接服务器及端口
fd = s.makefile('rw',0)        #创建文件类型(模式,缓存)0为不关闭缓存模式                         
fd.write("/ \r\n")             #向文件类对象写入(可循环)
buf = fd.readlines()           #从文件类对象读取(可循环)
--------------------------------------------------------------------------
基本服务器操作(Server)
--------------------------------------------------------------------------
#s.bind(('', 80))函数第一个参数通常为空,标识绑定到所有的接口和地址
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  #设置成可复用的
s.bind((‘’, 51423))  #主机设置为空可以接受来自任意地方的连接,并设置端口
s.listen(1)            #开始等候来自客户端的连接,每次最多只有一个等候处理
while 1:               #↓s.accept()返回一个新连接客户端的socket和客户端IP
    clientsock, clientaddr = s.accept()
    clientfile = clientsock.makefile('rw',0)   #创建文件类型,读写,关缓存
    clientfile.write("Welcome, " + str(clientaddr) + "\n")       #发数据
    clientfile.write("Pleass enter a string:")                   #发数据
    line = clientfile.readline().strip()                         #收数据
    clientfile.write("You entered %d characters.\n" % len(line)) #发数据
    clientfile.close()                                           #关闭
    clientsock.close()                                           #关闭
--------------------------------------------------------------------------
高级接口
--------------------------------------------------------------------------
f = gopherlib.send_selector(file, host)  #建立socket和连接[f.readlines()]
f = urllib.urlopen('http://%s%s' % (host, file))            #f.read()下载
--------------------------------------------------------------------------
寻找端口号(/etc/services) -> 从socket获取信息
--------------------------------------------------------------------------
port = socket.getservbyname('http', 'tcp')   #寻找TCP(UDP)的HTTP协议端口号
s.connetc(("", port))          #通过寻找到的端口号连接
print "Connected from", s.getsockname()      #显示本身的IP地址和端口号
print "Connected to",   s.getpeername()      #显示服务器的IP地址和端口号
--------------------------------------------------------------------------
使用UDP(Client)
--------------------------------------------------------------------------
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
port = socket.getservbyname('http','udp')
s.connect((host, port))
s.sendall(data)
buf = s.recv(2048)
--------------------------------------------------------------------------
有时使用UDP可以根本不调用connect()
--------------------------------------------------------------------------
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
host = socket.gethostbyname('time.nist.gov')                 #获取IP地址
s.sendto('', (host, port))            #调用sendto向服务器发送一个空字符串
buf = s.recvform(2048)   #返回(touple)内容为接收的数据和发送数据的机器地址
--------------------------------------------------------------------------
使用UDP(Server)
--------------------------------------------------------------------------
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))                          #
message, address = s.recvfrom(8192)           #接收数据(可循环)
s.sendto(message, address)                    #发送数据(可循环)
--------------------------------------------------------------------------
连接UDP(Server)的(Client)
--------------------------------------------------------------------------
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto('aaaa',("192.168.35.139", 51423))
print s.recvfrom(2048)
--------------------------------------------------------------------------
设置和得到socket选项
--------------------------------------------------------------------------
#通常服务器会在进程终止后保留几分钟该程序端口,防止超时使用该端口
s.socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#SO_REUSEADDR 标记为true,系统会在服务器socet被关闭后马上释放该服务器端口
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)     #设置
s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)     #查看
--------------------------------------------------------------------------
SO_BINDTODEVICE
SO_BROADCAST
SO_DONTROUTE
SO_KEEPALIVE
SO_OOBINLINE
SO_REUSEADDR
SO_TYPE
--------------------------------------------------------------------------
通过syslog来记录日志
--------------------------------------------------------------------------
#syslog模块在开始记录信息前需要调用openlog()函数来初始化syslog接口
openlog(标识符信息(例如进程名称,ID等)[, 选项[, 工具]])
syslog.openlog("%s[%d]" % (os.path.basename(),os.getpid(),0,syslog.LOG_DAEMON)
--------------------------------------------------------------------------
#LOG_CONS   访问不到机器的syslog进程或记录信息错误时,在系统控制台显示该信息
#LOG_NDELAY 不进行任何延时就打开syslog程序的连接
#LOG_NOWAIT 在系统上建立一个新的进程来记录信息
#LOG_PID    自动在每条日志信息中包含进程ID
#LOG_PERROR 错误除了记录到syslog中,还会在stderr打印出来
--------------------------------------------------------------------------
#LOG_AUTH    认证信息:登录,退出
#LOG_CRON    来自自动命令日程安排程序的信息
#LOG_DAEMON  任何不能被归纳如日志种类的系统服务器信息
#LOG_KERN    操作系统的核心信息
#LOG_LOGCALx 从LOG_LOCAL0到LOG_LOCAL7为本地使用,由管理员定制
#LOG_LPR     打印服务器信息
#LOG_MAIL    和邮件有关的信息
#LOG_NEWS    Usernet新闻信息
#LOG_USER    用户定义的普通且非特殊的信息
#LOG_UUCP    UNIX-to-UNIX Copy Protocol(UUCP)信息
--------------------------------------------------------------------------
↑(初始化完毕)现在可以实际记录一条信息
--------------------------------------------------------------------------
syslog([重要性,] message)
syslog.syslog(syslog.LOG_ERR,"System Error")
#LOG_EMERG   紧急情况,整个系统非正常关机或不能使用
#LOG_ALERT   向管理员发出警报;需要立即采取措施
#LOG_CRIT    一个知名的错误已经发生
#LOG_ERR     一个普通错误发生
#LOG_WARNING 一条警告被记录
#LOG_NOTICE  对于一个重要的正常情况的通知
#LOG_INFO    普通信息
#LOG_DEBUG   调试信息;通常被丢弃
--------------------------------------------------------------------------
域名系统(DNS) ->正向查找
------------------------------------------------
#getaddrinfo(地址,端口[,家族[,类型[,原始[,标记]]]])
#返回tuple:(家族, 类型, 原始, 标准名, 地址)
#正向查找捕获异常错误为:socket.gaierror
socket.getaddrinfo("域名",None) ↓不显示重复
socket.getaddrinfo("域名",None,0,socket.SOCK_STRAM)
------------------------------------------------
socket.gethostbyname()   #域名解析,不支持IPv6
------------------------------------------------
域名系统(DNS) ->反向查找
------------------------------------------------
#确保为每个反向查找的行为捕获和处理socket.herror
------------------------------------------------
try:
    socket.gethostbyaddr("IP地址")
except socket.herror, e:
    print "Couldn't look up name:", e
------------------------------------------------
域名系统(DNS) ->对反向查找数据真实性检查
------------------------------------------------
x = socket.gethostbyaddr("IP地址")[0]
f = socket.getaddrinfo(x,None,0,socket.SOCK_STREAM)
if not IP地址 in f: print "Error IPaddress"
------------------------------------------------
域名系统(DNS) ->获得环境信息
------------------------------------------------
socket.gethostname()  #获取系统本地主机名
socket.getfqdn()      #获取主机名并试图取完整数据
------------------------------------------------
使用PyDNS库的DNS模块
------------------------------------------------
#查找系统配置的DNS,Linux:resolv.conf,Win:注册表
DNS.DiscoverNameServers()
#也可以手动指定DNS地址
DNS.defaults['server']=['202.106.0.20','8.8.8.8']
------------------------------------------------
#建立一个请求对象,通过该对象发出任何DNS查询请求
find = DNS.Request()
#请求对象的req()方法用来执行实际查询
#参数:name:给出实际查询的名称
#参数:qtype,制订了前面列表中的某条record类型
info=find.req(name='baidu.com',qtype=DNS.Type.ANY)
#↑应答对象有个属性叫answers,其中包含所有返回的应答列表
info.answers
------------------------------------------------
半开放socket
------------------------------------------------
socket.shutdown(参数)
#参数 0 表示禁止将来读
#参数 1 表示禁止将来写
#参数 2 标识禁止将来读写
#对参数的设置是累积的,先0后1相当于2
------------------------------------------------
Socket超时
------------------------------------------------
#如果超过了设置时间,则产生:socket.timeout异常       
clientk, clientr = s.accept()
clientk.settimeout(15)  #超过10秒无操作则超时断开
------------------------------------------------
字符串结束标识符:
------------------------------------------------
#发送字符串之前先发送一个位移的字符串结束标识
#待字符串发送完成后,发送字符串结束标识
#或者发送字符串之前先发送一个要发送字符串的大小
------------------------------------------------
理解网络字节顺序
------------------------------------------------
#在网络上发送整型数据的时候,通常有两种选择:
#一个ASCII码的字符串,接收方需要解析;
#一个二进制字,一般是16或32位长;
------------------------------------------------
#struct模块支持数据在Python和二进制质检的转换
#主要使用两种格式:H(16位整数),I(32位整数)
#struct.pack(接收整型),struct.unpack(接收字符串)
------------------------------------------------
x = struct.pack('!H',len('test')) #长度转化!H
y = struct.pack('!I',len('test')) #长度转化!I
m = struct.unpack('!H','test')[0] #字符转化!H
z = struct.unpack('!I','test')[0] #字符转化!I
struct.pack('!H',m)               #转化回来!H
struct.pack('!I',z)               #转化回来!I
------------------------------------------------
使用广播数据 ->Server
------------------------------------------------
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
#↓开启广播功能,将具备接收和处理广播和非广播数据的能力
s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
s.bind((host, port))
message, address = s.recvfrom(8192)
s.sendto('I am here', address)
------------------------------------------------
使用广播数据 ->Client
------------------------------------------------
dest = ('',51423)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
s.sendto("hello",dest)
(buf,address) = s.recvfrom(2048)
------------------------------------------------
绑定到特殊的地址
------------------------------------------------
host = '127.0.0.1'     #则127.0.0.1为绑定到的地址
port = 51423
------------------------------------------------
使用poll()或select()实现时间通知
------------------------------------------------
------------------------------------------------
------------------------------------------------
------------------------------------------------
------------------------------------------------

阅读(3299) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~