socket编程
2018-06-17 23:28:54来源:未知 阅读 ()
一.socket介绍
1.socket在tcp/ip五层结构中的位置
socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
2.类型
基于文件类型的套接字家族
套接字家族的名字:AF_UNIX
unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
基于网络类型的套接字家族
套接字家族的名字:AF_INET
(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)
3.套接字工作流程
服务端套接字函数
s.bind() 绑定(主机,端口号)到套接字
s.listen() 开始TCP监听
s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来
客户端套接字函数
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
公共用途的套接字函数
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() 关闭套接字
面向锁的套接字方法
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间
面向文件的套接字的函数
s.fileno() 套接字的文件描述符
s.makefile() 创建一个与该套接字相关的文件
二.基于TCP的套接字
1.以打电话为例实现套接字通信
import socket #买手机 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #tcp协议 #绑定手机卡 phone.bind(('127.0.0.1',8080)) #开机 phone.listen(5) #最大挂起的连接数 #等待连接 print('starting...') conn,client_addr=phone.accept() #(套接字链接,客户端的ip和port) print('>>>>>>>') #收消息 data=conn.recv(1024) #1024最大的限制 print('客户端消息:',data) #发消息 conn.send(data.upper()) #挂电话 conn.close() #关机 phone.close()
import socket #买手机 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #tcp协议 #发起连接 phone.connect(('127.0.0.1',8080)) #发消息 phone.send('hello world'.encode('utf-8')) #收消息 data=phone.recv(1024) print(data) #关机 phone.close()
2.加上链接循环与通信循环
import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #tcp协议 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('127.0.0.1',8080)) phone.listen(5) #最大挂起的连接数 while True: conn,client_addr=phone.accept() #(套接字链接,客户端的ip和port) print(client_addr) while True: #通信循环 try: data=conn.recv(1024) #1024最大的限制 print('客户端消息:',data) if not data:break #针对Linux系统 conn.send(data.upper()) except ConnectionResetError: break conn.close() phone.close()
import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #tcp协议 phone.connect(('127.0.0.1',8080)) while True: msg=input('>>:').strip() if not msg: continue phone.send(msg.encode('utf-8')) data=phone.recv(1024) print(data.decode('utf-8')) phone.close()
3.实现ssh远程执行命令
import socket,subprocess phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #tcp协议 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('127.0.0.1',8080)) phone.listen(5) #最大挂起的连接数 while True: conn,client_addr=phone.accept() #(套接字链接,客户端的ip和port) print(client_addr) while True: #通信循环 try: cmd=conn.recv(1024) #1024最大的限制 print('客户端消息:',cmd) if not cmd:break #针对Linux系统 obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_res=obj.stdout.read() stderr_res=obj.stderr.read() conn.send(stdout_res+stderr_res) except ConnectionResetError: break conn.close() phone.close()
import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #tcp协议 phone.connect(('127.0.0.1',8080)) while True: cmd=input('>>:').strip() if not cmd: continue phone.send(cmd.encode('utf-8')) cmd_res=phone.recv(1024) print(cmd_res.decode('gbk')) phone.close()
三.粘包
处理粘包1(加上固定长度的报头):
import socket,subprocess,struct phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #tcp协议 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('127.0.0.1',8080)) phone.listen(5) #最大挂起的连接数 while True: conn,client_addr=phone.accept() #(套接字链接,客户端的ip和port) print(client_addr) while True: #通信循环 try: cmd=conn.recv(1024) #1024最大的限制 print('客户端消息:',cmd) if not cmd:break #针对Linux系统 obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_res=obj.stdout.read() stderr_res=obj.stderr.read() #先发报头 data_size=len(stdout_res)+len(stderr_res) conn.send(struct.pack('i',data_size)) conn.send(stdout_res) conn.send(stderr_res) except ConnectionResetError: break conn.close() phone.close()
import socket,struct phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #tcp协议 phone.connect(('127.0.0.1',8080)) while True: cmd=input('>>:').strip() if not cmd: continue phone.send(cmd.encode('utf-8')) #先收报头 head_strct=phone.recv(4) total_size=struct.unpack('i',head_strct)[0] cmd_res=b'' recv_size=0 while recv_size<total_size: recv_data=phone.recv(1024) cmd_res+=recv_data recv_size+=len(recv_data) print(cmd_res.decode('gbk')) phone.close()
处理粘包2(加上反映数据信息的报头,和报头长度):
import socket,subprocess,struct,json phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #tcp协议 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('127.0.0.1',8080)) phone.listen(5) #最大挂起的连接数 while True: conn,client_addr=phone.accept() #(套接字链接,客户端的ip和port) print(client_addr) while True: #通信循环 try: cmd=conn.recv(1024) #1024最大的限制 print('客户端消息:',cmd) if not cmd:break #针对Linux系统 obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_res=obj.stdout.read() stderr_res=obj.stderr.read() #制作报头 head_dic={ 'filename':'a.txt', 'total_size':len(stdout_res)+len(stderr_res), 'md5':'fiwehfoaejrfanf' } head_json=json.dumps(head_dic).encode('utf-8') #先发报头长度 conn.send(struct.pack('i',len(head_json))) #再发报头 conn.send(head_json) #再发数据 conn.send(stdout_res) conn.send(stderr_res) except ConnectionResetError: break conn.close() phone.close()
import socket,struct,json phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #tcp协议 phone.connect(('127.0.0.1',8080)) while True: cmd=input('>>:').strip() if not cmd: continue phone.send(cmd.encode('utf-8')) #先收报头长度 struct_res=phone.recv(4) head_size=struct.unpack('i',struct_res)[0] #先收报头 head_json=phone.recv(head_size).decode('utf-8') head_dic=json.loads(head_json) cmd_res=b'' recv_size=0 total_size=head_dic['total_size'] while recv_size<total_size: recv_data=phone.recv(1024) cmd_res+=recv_data recv_size+=len(recv_data) print(cmd_res.decode('gbk')) phone.close()
四. 基于UDP的套接字
#服务器端 import socket ip_port=('127.0.0.1',9000) BUFSIZE=1024 #创建一个服务器的套接字 udp_server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #绑定服务器套接字 udp_server.bind(ip_port) while True: #接收 msg,addr=udp_server.recvfrom(BUFSIZE) print(msg,addr) #发送 udp_server.sendto(msg.upper(),addr) udp_server.close()
import socket ip_port=('127.0.0.1',9000) BUFSIZE=1024 # 创建客户套接字 udp_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True: msg=input('>>: ').strip() if not msg:continue #发送 udp_client.sendto(msg.encode('utf-8'),ip_port) #接收 back_msg,addr=udp_client.recvfrom(BUFSIZE) print(back_msg.decode('utf-8'),addr)
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- python3基础之“术语表(2)” 2019-08-13
- 网络编程相关知识点 2019-08-13
- python 之 并发编程(线程理论,开启线程的两种方式,进程 2019-07-24
- 编程小白的第一本python入门书(高清版)PDF下载 2019-07-24
- python 之 并发编程(生产者消费者模型、守护进程的应用) 2019-07-24
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash