Python常用模块之六 socket
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() #创建一个与该套接字相关连的文件