Python 提供了两个基本的 socket 模块。
第一个是 Socket,它提供了标准的 BSD Sockets API。
第二个是 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。
1、socket数据类型
socket类型在Liunx和Python是一样的, 只是Python中的类型都定义在socket模块
中, 调用方式socket.SOCK_XXXX
1)流式socket(SOCK_STREAM) 用于TCP通信
2)数据报socket(SOCK_DGRAM) 用于UDP通信
3)原始socket(SOCK_RAW) 用于新的网络协议实现的测试等
4)socket.AF_INET 用于服务器之间网络通信
2. Socket编程
2.1. TCP通信
TCP通信的基本步骤如下:
服务端:socket---bind---listen---while(True){---accept------send----}---close
客户端:socket-------connect---send---recv-------close
2.2. 简单的客户端服务器TCP连接
一个简单的回显服务器和客户端模型, 客户端发出的数据, 服务器会回显到客户端的终端上(只是一个简单的模型, 没考虑错误处理等问题)。
#服务器端
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket #socket模块
import commands #执行系统命令模块
BUF_SIZE = 1024 #设置缓冲区大小
server_addr = ('127.0.0.1', 8888) #IP和端口构成表示地址
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #生成一个新的socket对象
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #设置地址复用
server.bind(server_addr) #绑定地址
server.listen(5) #监听, 最大监听数为5
while True:
client, client_addr = server.accept() #接收TCP连接, 并返回新的套接字和地址
print 'Connected by', client_addr
while True :
data = client.recv(BUF_SIZE) #从客户端接收数据
print data
client.sendall(data) #发送数据到客户端
server.close()
#客户端
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
BUF_SIZE = 1024 #设置缓冲区的大小
server_addr = ('127.0.0.1', 8888) #IP和端口构成表示地址
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #返回新的socket对象
client.connect(server_addr) #要连接的服务器地址
while True:
data = raw_input("Please input some string > ")
client.sendall(data) #发送数据到服务器
data = client.recv(BUF_SIZE) #从服务器端接收数据
print data
client.close()
2.3. UDP通信
UDP通信流程图如下:
服务端:socket---bind---recvfrom---sendto---close
客户端:socket---sendto---recvfrom---close
2.4. 简单的客户端服务器UDP连接
#服务器端
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
BUF_SIZE = 1024 #设置缓冲区大小
server_addr = ('127.0.0.1', 8888) #IP和端口构成表示地址
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #生成新的套接字对象
server.bind(server_addr) #套接字绑定IP和端口
while True :
print "waitting for data"
data, client_addr = server.recvfrom(BUF_SIZE) #从客户端接收数据
print 'Connected by', client_addr, ' Receive Data : ', data
server.sendto(data, client_addr) #发送数据给客户端
server.close()
#客户端
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import struct
BUF_SIZE = 1024 #设置缓冲区
server_addr = ('127.0.0.1', 8888) #IP和端口构成表示地址
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #生成新的套接字对象
while True :
data = raw_input('Please Input data > ')
client.sendto(data, server_addr) #向服务器发送数据
data, addr = client.recvfrom(BUF_SIZE) #从服务器接收数据
print "Data : ", data
client.close()
2.5. 其他
s.getpeername()
#返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
s.getsockname()
#返回套接字自己的地址。通常是一个元组(ipaddr,port)
s.setsockopt(level,optname,value)
#设置给定套接字选项的值。
s.getsockopt(level,optname[.buflen])
#返回套接字选项的值。
s.settimeout(timeout)
#设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect())
s.gettimeout()
#返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。
s.fileno()
#返回套接字的文件描述符。
s.setblocking(flag)
#如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。
s.makefile()
#创建一个与该套接字相关连的文件
详见:http://www.jianshu.com/p/e062b3dd110c