06.26自我总结
1.关于Socket
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
socket模板已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。
- 注意:也有人将socket说成ip+port,ip是用来标识互联网中的一台主机的位置,而port是用来标识这台机器上的一个应用程序,ip地址是配置到网卡上的,而port是应用程序开启的,ip与port的绑定就标识了互联网中独一无二的一个应用程序,而程序的pid是同一台机器上不同进程或者线程的标识。
2.套接字工作流程
3.套接字的函数
s都为通过socket模块生成
import socket
# socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,默认值为 0
socket.socket(socket_family, socket_type, protocal=0)
# 获取tcp/ip套接字
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取udp/ip套接字
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 由于 socket 模块中有太多的属性。我们在这里破例使用了'from module import *'语句。使用 'from socket import *',我们就把 socket 模块里的所有属性都带到我们的命名空间里了,这样能大幅减短我们的代码
s = socket(AF_INET, SOCK_STREAM)
1.服务器套接字函数
方法 |
用途 |
s.bind() |
绑定(主机,端口号)到套接字 注:(127.0.0.1)表示本地ip |
s.listen() |
开始TCP监听 |
s.accept() |
被动接受TCP客户的连接,(阻塞式)等待连接的到来 |
2.客户端套接字函数
方法 |
用途 |
s.connect() |
主动初始化TCP服务器连接 |
s.connect_ex() |
connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 |
3.公共用途的函数
方法 |
用途 |
s.recv() |
接收TCP数据 |
s.send() |
发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完) |
s.sendall() |
发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完) |
s.recvfrom() |
接收UDP数据 |
s.sendto() |
发送UDP数据 |
s.getpeername() |
连接到当前套接字的远端的地址 |
s.getsockname() |
当前套接字的地址 |
s.getsockopt() |
返回指定套接字的参数 |
s.setsockopt() |
设置指定套接字的参数 |
s.close() |
关闭套接字 |
4.面向锁套接字
方法 |
用途 |
s.setblocking() |
设置套接字的阻塞与非阻塞模式 |
s.settimeout() |
设置阻塞套接字操作的超时时间 |
s.gettimeout() |
得到阻塞套接字操作的超时时间 |
5.面向文件套接字
方法 |
用途 |
s.fileno() |
套接字的文件描述符 |
s.makefile() |
创建一个与该套接字相关的文件 |
4.示例
1.服务端
import socket
#1、买手机
phone = socket.socket(socket.AF_INET,
socket.SOCK_STREAM) #tcp称为流式协议,udp称为数据报协议SOCK_DGRAM
# print(phone)
#2、插入/绑定手机卡
# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1', 8080))
#3、开机
phone.listen(5) # 半连接池,限制的是请求数
#4、等待电话连接
print('start....')
while True: # 连接循环
conn, client_addr = phone.accept() #(三次握手建立的双向连接,(客户端的ip,端口))
# print(conn)
print('已经有一个连接建立成功', client_addr)
#5、通信:收\发消息
while True: # 通信循环
try:
print('服务端正在收数据...')
data = conn.recv(1024) #最大接收的字节数,没有数据会在原地一直等待收,即发送者发送的数据量必须>0bytes
# print('===>')
if len(data) == 0: break #在客户端单方面断开连接,服务端才会出现收空数据的情况
print('来自客户端的数据', data)
conn.send(data.upper())
except ConnectionResetError:
break
#6、挂掉电话连接
conn.close()
#7、关机
phone.close()
2.客户端
import socket
#1、买手机
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# print(phone)
#2、拨电话
phone.connect(('127.0.0.1', 8080)) # 指定服务端ip和端口
#3、通信:发\收消息
while True: # 通信循环
msg = input('>>: ').strip() #msg=''
if len(msg) == 0: continue
phone.send(msg.encode('utf-8'))
# print('has send----->')
data = phone.recv(1024)
# print('has recv----->')
print(data)
#4、关闭
phone.close()