基于TCP协议的套接字编程
程序员文章站
2022-05-15 13:33:50
06.26自我总结 1.关于Socket Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议 ......
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()
上一篇: MySQL数据库使用时注意事项
下一篇: 清除浮动的几种方法