TCP编程与Socket
Socket介绍
Socket套接字
Python中提供socket.py标准库,非常底层的接口库。
Socket是一种通用的网络编程接口,和网络层次没有一一对应关系。
- 协议族
AF表示Address Family,用于socket()第一个参数
名称 | 含义 |
---|---|
AF_INET | IPV4 |
AF_INET6 | IPV6 |
AF_UNIX | Unix Domain Socket,windows没有 |
- Socket类型
名称 | 含义 |
---|---|
SOCK_STREAM | 面向链接的流套接字。默认值,TCP协议 |
SOCK_DGRAM | 无链接的数据报文套接字。UDP协议 |
- socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) #构建一个socket对象
TCP编程
Socket编程,需要两端,一般来说需要一个服务端、一个客户端,服务端称为Server,客户端称为Client
这种编程模式也称为cs编程
TCP服务端编程
- 创建Socket对象
- 绑定IP地址Address和端口Port。bind()方法。(IPV4地址位一个二元组(“IP地址字符串”,Port))
- 获取用于传送数据的Socket对象
- socket.accept()–>(socket object,addreass info)
- accept方法阻塞等待客户端建立连接,返回一个新的Socket对象和客户端地址的二元组
- 地址是远程客户端的地址,IPV4中它是一个二元组(clientaddr,prot)
- 接受数据
- revc(bufzize[,flags])使用缓冲区接受数据
- 发送数据
- send(bytees)发送数据
- 接受数据
- 简单示例,创建一个简单的服务,实现监听一次,接受一次用户输出,并传递一个消息给用户。
import socket
#创建一个socket
service = socket.socket()
#绑定ip和端口
service.bind(("127.0.0.1",3999))
#启动监听
service.listen()
#等待用户接入
clsock,client = service.accept()
print("用户已近链接")
#等待用户发送消息
date = clsock.recv(1024)
print("收到用户发来消息:{}".format(date))
clsock.send("service -> {}".format(date).encode())
clsock.close() #和用户断开链接
service.close() #关闭service
print("服务器已近关闭")
- 服务端输出:
- 客户端连接输入:
socket常用属性
名称 | 含义 |
---|---|
socket.getpeername() | 返回链接套接字的远程地址。返回值通常是元组(ipaddr,port) |
socket.getsockname() | 返回套接字自己的地址。通常是一个元组(ipaddr,port) |
socket.setblocking(flag) | 如果flag为0,则将套接字设为非阻塞模式,否则套接字设为阻塞模式(默认值) 非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常 |
socket.settimeout(value) | 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。 一般,超时期应该在刚创建套接字时设置,因为他们可能用于连接的操作(如connect()) |
socket.setsockopt(level,optname,value) | 设置套接字选项的值。比如缓冲区太小。太多了,不同系统,不同版本都不尽相同(详细请看文档) |
socket常用方法
名称 | 含义 |
---|---|
socket.recv(bufsize[,flags]) | 获取数据。默认是阻塞的方式 |
socket.revfrom(bufsize[,flags]) | 获取数据,返回一个二元组(bytes,address) |
socket.recv_into(buffer[,nbytes[,flags]]) | 获取到nbytes的数据后,存储到buffer中。如果nbytes没有指定或0,将buffer大小的数据存入buffer中。返回接受的字节数。 |
socket.recfrom_into(buffer[,nbytes[,flags]]) | 获取数据,返回一个二元组(bytes,address)到buffer中 |
socket.send(bytes[,flags]) | TCP发送数据 |
socket.sendall(bytes[,flags]) | TCP发送全部数据,成功返回None |
socket.sendto(string[,flag],address) | UDP发送数据 |
socket.sendfile(file,offset=0,count=None) | 发送一个文件直到EOF,使用高性能的os.sendfile机制,返回发送的字节数。如果win下不支持sendfile,或者不是普通文件,使用send()发送文件。offset告诉起始位置。3.5版本开始 |
MakeFile
- socket.makefile(mode=‘r’, buffering=None, *, encoding=None, errors=None, newline=None) #创建一个与该套接字相关连的文件对象,将recv方法看做读方法,将send方法看做写方法。
- mode:文件对象的模式,只支持"wra"三种模式的组合,不支持"w+"等,带加号这种。
- buffering:缓存区大小
- encoding:编码
- errors:什么样的编码错误将被捕获。默认值为None
- nowline:换行符
- 注意:socket.makefile构造方法中的参数与open对象参数大致相同。
- 注意:makefile实质是在内存中构建了一个文件对象。文件并不是真的存在。类似于StringIO
- 简单示例:
import socket
server