python 网络编程 socket
socket网络套接字,提供基础的网络编程服务
SocketServer 提供较高级的服务,简化网络编程
socket提供如下方法:
1.exception socket.error
套接字相关的错误,返回(errno, string),或者一个字符串。socket.error 是IOError错误的一种
2.exception socket.herror
调用gethostbyname_ex(), gethostbyaddr() 抛出的主机与地址错误 ,返回(h_errno, string) ,string是c函数hstrerror()返回
3.exception socket.gaierror
地址相关的错误,一般是调用getaddrinfo(),getnameinfo()时。返回(error, string),string是错误的具体描述,是由c函数gai_strerror()返回。
error的值是定义为EAI_* 中的一个值
4.exception socket.timeout 超时
socket.AF_UNIX
socket.AF_INET
socket.AF_INET6
socket.SOCK_STREAM
socket.SOCK_DGRAM
socket.SOCK_RAW
socket.SOCK_RDM
socket.SOCK_SEQPACKET
比较常用的是:socket.SOCK_STREAM ,socket.SOCK_DGRAM
1.socket.create_connection(address[, timeout[, source_address]])
建立tcp连接,地址(host, port),返回一个socket对象,比socket.connect()高级
如果host是非数字的ip地址,则会使用AF_INET and AF_INET6进行地址解析
timeout超时,若没有指定,则设置为默认,默认值可以使用getdefaulttimeout()
source_address源端地址(host, port) 如果host或者port是”或0,则使用默认的
2.socket.getaddrinfo(host, port[, family[, socktype[, proto[, flags]]]])
获取地址信息返回(family, socktype, proto, canonname, sockaddr)5元组
例如:
>>> import socket
>>> socket.getaddrinfo("example.org", 80, 0, 0, socket.IPPROTO_TCP)
[(2, 1, 6, '', ('93.184.216.34', 80)), (10, 1, 6, '', ('2606:2800:220:1:248:1893:25c8:1946', 80, 0, 0))]
>>>
3.socket.getfqdn([name])
获取完整域名
4.socket.gethostbyname(hostname)
dns解析,主机名解析为ip
5.socket.gethostbyname_ex(hostname)
gethostbyname的扩展,返回主机名,ip,别名
6.socket.gethostname()
返回主机名gethostbyname(gethostname()).可以获得当前主机的ip
7.socket.gethostbyaddr(ip_address)
返回(hostname, aliaslist, ipaddrlist),获取一个ip的dns信息
8.socket.getnameinfo(sockaddr, flags)
给定ip返回(host, port)
9.socket.getprotobyname(protocolname)
协议映射到数字
10.socket.getservbyname(servicename[, protocolname])
将服务映射到端口 protocolname可以是tcp或udp,其他的都是全匹配
11.socket.getservbyport(port[, protocolname])
根据端口获取服务名
12.socket.getdefaulttimeout()
获取默认超时
13.socket.setdefaulttimeout(timeout)
设置默认超时
14.socket.socketpair([family[, type[, proto]]])
用给定地址家族建立连接
15.socket.fromfd(fd, family, type[, proto])
用一个打开的文件描述符创建套接字对象
16.主机字节序与网络字节序转换,详情参看手册
socket.ntohl(x)
socket.ntohs(x)
socket.htonl(x)
socket.htons(x)
17.socket.socket([family[, type[, proto]]])
socket对象提供如下方法:
服务器端套接字
socket.bind(address) 绑定套接字, 在AF_INET下,以元组(host,port)的形式表示地址。
socket.listen() 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,一般设置为5即可。
socket.accept() 被动接受TCP客户端连接,(阻塞式)等待连接的到来,返回(conn, address)
客户端套接字
socket.connect(address) 服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
socket.connect_ex(address) connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
公共用途的套接字函数
socket.recv() 接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。
socket.send() 发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。
socket.sendall() 完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
socket.recvfrom() 接收UDP数据,与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。
socket.sendto() 发送UDP数据,将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。
socket.close() 关闭套接字,它会释放连接资源,如果要及时关闭连接,则可以在close()之前使用shutdown()
socket.getpeername() 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
socket.getsockname() 返回套接字自己的地址。通常是一个元组(ipaddr,port)
socket.setsockopt(level,optname,value) 设置给定套接字选项的值。
socket.getsockopt(level,optname[.buflen]) 返回套接字选项的值。
socket.settimeout(timeout) 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect())
socket.gettimeout() 返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。
socket.fileno() 返回套接字的文件描述符。
socket.setblocking(flag) 如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。
socket.makefile() 创建一个与该套接字相关连的文件
socket.shutdown(how) how可以是:SHUT_WR不再发送 SHUT_RDWR不再发送和接收
如下模型:
服务端:
import socket
HOST = ''
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
conn.close()
客服端:
import socket
HOST = 'localhost' # The remote host
PORT = 50007 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)
输出:
服务端:
Connected by (‘127.0.0.1’, 43991)
客服端:
Received ‘Hello, world’
示例:
服务端:
#coding=utf8
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print 'get from :', addr
c.send('hello,welcome')
c.close()
客户端:
#coding=utf8
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.connect((host, port))
print s.recv(1024)
s.close()
输出:
客服端:
[root@myrpc t]# python cc.py
hello,welcome
[root@myrpc t]# python cc.py
hello,welcome
[root@myrpc t]# python cc.py
hello,welcome
[root@myrpc t]# python cc.py
hello,welcome
[root@myrpc t]# python cc.py
hello,welcome
服务端:
get from : ('192.168.137.19', 48552)
get from : ('192.168.137.19', 48553)
get from : ('192.168.137.19', 48554)
get from : ('192.168.137.19', 48555)
get from : ('192.168.137.19', 48556)
端口扫描:
import socket
import threading
from Queue import Queue
def scan(port):
s = socket.socket()
s.settimeout(1)
if s.connect_ex(('localhost', port)) == 0:
print "local open port : %d"%port
s.close()
def worker():
while not q.empty():
port = q.get()
try:
scan(port)
finally:
q.task_done()
if __name__ == '__main__':
q = Queue()
map(q.put,xrange(1,65535))
threads = [threading.Thread(target=worker) for i in xrange(100)]
map(lambda x:x.start(),threads)
q.join()