python 网络编程_Python socket网络编程(笔记)

--------------------------------------------------------------------------

#一个停止并等待输入或输出的程序成为被阻塞的程序

#死锁问题,在每次发送数据时接收端都接受一次,避免数据积压

--------------------------------------------------------------------------

基本客户端操作

--------------------------------------------------------------------------

#文件对象类型: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(("www.google.com", 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()实现时间通知

------------------------------------------------

------------------------------------------------

------------------------------------------------

------------------------------------------------

------------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值