python模块介绍- socket(2)
11.1.2 TCP / IP的客户端和服务器
socket可以配置为服务器或者客户端实现双向通信。
简单的回显网络程序。
服务器端的步骤如下:1,创建socket(socket.socket),设定地址族和套接字类型;2,绑定地址sock.bind();3,监听sock.listen(1);4,消息处理,先用sock.accept()接收数据,然后在通道上接收connection.recv(16)或者发送数据sendall(data)。
一旦开始监听,socket就进入服务器状态。listen(1)表示只能同时接纳一个连接。
客户端的步骤如下:1,创建socket(socket.socket),设定地址族和套接字类型;2,连接sock.connect(server_address);3,消息处理,先用sock.sendall()发送数据,然后在通道上接收sock.sendall。注意跟服务器端比,这里是直接操作sock,不是connection。
服务器端:
#!/usr/bin/envpython
#encoding: utf-8
#
#Copyright (c) 2010 Doug Hellmann. Allrights reserved.
#
"""Serverhalf of echo example.
"""
#end_pymotw_header
importsocket
importsys
#Create a TCP/IP socket
sock= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#Bind the socket to the port
server_address= ('localhost', 10000)
print>>sys.stderr, 'starting up on %s port %s' % server_address
sock.bind(server_address)
#Listen for incoming connections
sock.listen(1)
whileTrue:
# Wait for a connection
print >>sys.stderr, 'waiting for aconnection'
connection, client_address = sock.accept()
try:
print >>sys.stderr, 'connectionfrom', client_address
# Receive the data in small chunks andretransmit it
while True:
data = connection.recv(16)
print >>sys.stderr, 'received"%s"' % data
if data:
print >>sys.stderr,'sending data back to the client'
connection.sendall(data)
else:
print >>sys.stderr, 'nodata from', client_address
break
finally:
# Clean up the connection
connection.close()
客户端:
"""Clienthalf of echo example
"""
#end_pymotw_header
importsocket
importsys
#Create a TCP/IP socket
sock= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#Connect the socket to the port where the server is listening
server_address= ('localhost', 10000)
print>>sys.stderr, 'connecting to %s port %s' % server_address
sock.connect(server_address)
try:
# Send data
message = 'This is the message. It will be repeated.'
print >>sys.stderr, 'sending"%s"' % message
sock.sendall(message)
# Look for the response
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = sock.recv(16)
amount_received += len(data)
print >>sys.stderr, 'received"%s"' % data
finally:
print >>sys.stderr, 'closing socket'
sock.close()
执行结果:
$python ./socket_echo_server.py
startingup on localhost port 10000
waitingfor a connection
connectionfrom (’127.0.0.1’, 52186)
received"This is the mess"
sendingdata back to the client
received"age. It will be"
sendingdata back to the client
received" repeated."
sendingdata back to the client
received""
nodata from (’127.0.0.1’, 52186)
waitingfor a connection
$python socket_echo_client.py
connectingto localhost port 10000
sending"This is the message. It will be repeated."
received"This is the mess"
received"age. It will be"
received" repeated."
closingsocket
create_connection()可以更加快速的构建客户端,它使用getaddrinfo()查找连接参数,返回一个打开的socket连接,相当于省略了socket.socket(socket.AF_INET,socket.SOCK_STREAM)这一步。
"""Clienthalf of echo example
"""
#end_pymotw_header
importsocket
importsys
defget_constants(prefix):
"""Create a dictionarymapping socket module
constants to their names.
"""
return dict( (getattr(socket, n), n)
for n in dir(socket)
if n.startswith(prefix)
)
families= get_constants('AF_')
types= get_constants('SOCK_')
protocols= get_constants('IPPROTO_')
#Create a TCP/IP socket
sock= socket.create_connection(('localhost', 10000))
print>>sys.stderr, 'Family :',families[sock.family]
print>>sys.stderr, 'Type :',types[sock.type]
print>>sys.stderr, 'Protocol:', protocols[sock.proto]
print>>sys.stderr
try:
# Send data
message = 'This is the message. It will be repeated.'
print >>sys.stderr, 'sending"%s"' % message
sock.sendall(message)
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = sock.recv(16)
amount_received += len(data)
print >>sys.stderr, 'received"%s"' % data
finally:
print >>sys.stderr, 'closing socket'
sock.close()
上面的服务端监听localhost,只有本机可以访问。使用gethostname()返回的地址,可以供其他机器访问。如果服务器有多个接口,也就是说有多个ip,可以使用地址:INADDR_ANY同时监听所有接口。尽管socket模块定义了INADDR_ANY常量,但是是个整型值,在传递给bind()之前需要转换为点分十进制的字符串地址。不想转换可以直接使用“0.0.0.0”或者空字符串。可以通过getsockname()查看实际监听的地址。
11.1.3 UDP的客户端和服务器
UDP不需要建立连接,包的有效长度最大为65,507bytes,加上头部共65,535-byte。
服务器端的步骤如下:1,创建socket(socket.socket),设定地址族和套接字类型;2,绑定地址sock.bind();3,消息处理,先用sock.recvfrom(4096)接收数据,用sock.sendto(data,address)接收数据。注意这里的sendto需要加上目的地址。
客户端的步骤如下:1,创建socket(socket.socket),设定地址族和套接字类型;2消息处理,先用sock.sendto ()发送数据,然后用recvfrom接收sock.sendall。
书上的例子输出都是采用print>>sys.stderr,,我个人觉得直接print也可以。
"""Echothe data to the client without printing it on the console.
"""
#end_pymotw_header
importsocket
importsys
#Create a UDP socket
sock= socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#Bind the socket to the port
server_address= ('localhost', 10000)
print>>sys.stderr, 'starting up on %s port%s' % server_address
sock.bind(server_address)
whileTrue:
print >>sys.stderr, '\nwaiting toreceive message'
data, address = sock.recvfrom(4096)
print >>sys.stderr, 'received %sbytes from %s' % \
(len(data), address)
print >>sys.stderr, data
if data:
sent = sock.sendto(data, address)
print >>sys.stderr, 'sent %sbytes back to %s' % \
(sent, address)
客户端如下:
"""Clienthalf of echo example
"""
#end_pymotw_header
importsocket
importsys
#Create a UDP socket
sock= socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address= ('localhost', 10000)
message= 'This is the message. It will berepeated.'
try:
# Send data
print >>sys.stderr, 'sending"%s"' % message
sent = sock.sendto(message, server_address)
# Receive response
print >>sys.stderr, 'waiting toreceive'
data, server = sock.recvfrom(4096)
print >>sys.stderr, 'received"%s"' % data
finally:
print >>sys.stderr, 'closing socket'
sock.close()
执行结果:
$python ./socket_echo_server_dgram.py
startingup on localhost port 10000
waitingto receive message
received42 bytes from (’127.0.0.1’, 50139)
Thisis the message. It will be repeated.
sent42 bytes back to (’127.0.0.1’, 50139)
waitingto receive message
Thisis the client output
$python ./socket_echo_client_dgram.py
sending"This is the message. It will be repeated."
waitingto receive
received"This is the message. It will be repeated."
closingsocket
这部分的程序,主要不用使用IDE去执行服务器端,否则可能会报错。