为什么要学习socket?
我们学习这个东东就是为了完成C/S架构的开发
(C:指的是客户端;S:指的是服务端)
服务端就是提供服务的一端 ,而客户端听名字就知道指的是用户使用的一端
学习socket一定要先学习互联网协议:
c/s架构的软甲(应用层)是基于网络通信的====>网络的核心是一堆协议,协议既是标准,如果你想开发基于网络通信的软件就必须遵循这些标准(有点类似于某些软件的安装时出现的霸王条款,必须接受,否则就不让你安装)
socket()的用法
1 import socket #模块必须导入 2 socket.socket(socket_family,socket_type,protocal=0) 3 socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,默认值为 0。 4 5 获取tcp/ip套接字 6 tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 7 8 获取udp/ip套接字 9 udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 10 11 由于 socket 模块中有太多的属性。我们在这里破例使用了'from module import *'语句。使用 'from socket import *',我们就把 socket 模块里的所有属性都带到我们的命名空间里了,这样能 大幅减短我们的代码。 12 例如tcpSock = socket(AF_INET, SOCK_STREAM)函数大致用法
服务端套接字函数:
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() 关闭套接字
用打电话模拟socket
1 from socket import * 2 phone=socket(AF_INET,SOCK_STREAM) 3 phone.bind(('127.0.0.1',8081)) 4 phone.listen(5) 5 6 conn,addr=phone.accept() 7 while True: 8 data=conn.recv(1024) 9 print('server===>') #测试代码 10 print(data) #同↑ 11 conn.send(data.upper()) 12 conn.close() 13 phone.close()服务端
1 from socket import * 2 3 phone=socket(AF_INET,SOCK_STREAM) 4 phone.connect(('127.0.0.1',8081)) 5 6 while True: 7 msg=input('>>: ').strip() 8 phone.send(msg.encode('utf-8')) 9 print('client====>') 10 data=phone.recv(1024) 11 print(data)客户端
基于TCP的小例子:
import socket #导入socket模块 import subprocess #后期处理系统文件用 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #phone:套接字的创建 # phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR) #这句代码主要功能是解决地址的冲突 phone.bind(('127.0.0.1',8080)) #套接字与IP和端口的绑定 phone.listen(5) #当与多台客户端通信时挂起的主机数 print('starting running .... #这里是做测试的,可以删掉') while True: #链接循环,否则就会卡主不动 conn,client_addr = phone.accept() #等待客户端发起通信 print('------->',conn,client_addr) #查看着两者的属性 while True: #通信循环功能 try: #异常处理 cmd = conn.recv(1024) if not cmd:break res = subprocess.Popen(cmd.decode('utf-8'),shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = res.stdout.read() stderr = res.stderr.read() conn.send(stdout+stderr) except Exception: break #出现异常直接结束 conn.close() #挂电话操作 phone.close() #关机操作
import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',8080)) while True: cmd = input('>>>:a').strip() if not cmd:continue phone.send(cmd.encode('utf-8')) cmd_res = phone.recv(1024) print(cmd_res.decode('gbk')) phone.close()