socket 是一组接口,将复杂的TCP/IP协议封装在接口内,我们只需要遵循socket的规定去编程就可以了。
套接字:
基于文件类型的套接字:AF_UNIX
在Unix系统上,基于文件的套接字运行在同一台机器上,通过访问同一个文件间接完成通信。
基于网络类型的套接字:AF_INET
套接字工作流程:
socket()模块函数用法
服务端套接字函数:
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直到发完)
s.recvfrom() 接收UDP数据
s.sendto() 发送UDP数据
s.getpeername() 连接当前套接字的远端地址
s.getsocketname() 当前套接字的地址
s.getsockopt 返回当前套接字的参数
s.setsockopt() 设置指定套接字的参数
s.close() 关闭套接字
面向锁的套接字方法:
s.setblocking() 设置套接字的阻塞与非阻塞方式
s.settimeout() 设置套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间
面向文件的套接字的函数:
s.fileno() 套接字的文件描述符
s.makefile() 创建一个与该套接字相关的文件
实例:利用打电话模拟socket通信
简单的套接字:
import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买电话 phone.bind(('192.168.20.6',8090)) phone.listen(5) print('string......') conn,client_adrr = phone.accept()#等电话,三次握手得到的双向链接,和客户端的IP及端口组成的元祖分别赋值给conn client_addr print(conn,client_adrr) #收,发消息 服务端是先收再发 data = conn.recv(1024)#设置最大接收为1024个字节 print('client data:<%s>'%data) conn.send(data.upper()) conn.close() phone.close()
import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机 phone.connect(('192.168.20.6',8090))#绑定手机卡 #发,收 消息 phone.send('hello sb'.encode('utf-8')) data = phone.recv(1024) print('sever back res <%s>'%data) phone.close()
循环通信:
import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bind(('192.168.20.6',9080)) phone.listen(5) print('string.....') conn,client_adrr = phone.accept() print(conn,client_adrr)#通信建立成功打印 while True: data = conn.recv(1024) print('client data:<%s>'%data) conn.send(data.upper()) conn.close() phone.close()
import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('192.168.20.6',9080)) #发,收消息 while True: msg = input('>>>:') if not msg:continue phone.send(msg.encode('utf-8')) data = phone.recv(1024) print('sever back data:<%s>'%data) phone.close()
加上链接的循环,上面两种方法一次都只能有一个客户端访问,利用链接循环,挨个访问
import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('192.168.20.6',8889)) phone.listen(5) while True: print('string.....') conn,client_addr = phone.accept() print(conn,client_addr) while True: try: data = conn.recv(1024) if not data:break print('client data:<%s>'%data) conn.send(data.upper()) except Exception: break conn.close() phone.close()
import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('192.168.20.6',8889)) while True: msg = input(">>>:").strip() if not msg:continue phone.send(msg.encode('utf-8')) data = phone.recv(1024) print('server back res:<%s>'%data) phone.close()
import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('192.168.20.6',8889)) while True: msg = input(">>>:").strip() if not msg:continue phone.send(msg.encode('utf-8')) data = phone.recv(1024) print('server back res:<%s>'%data) phone.close()
import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('192.168.20.6',8889)) while True: msg = input(">>>:").strip() if not msg:continue phone.send(msg.encode('utf-8')) data = phone.recv(1024) print('server back res:<%s>'%data) phone.close()
模拟ssc远程控制:
import socket import subprocess #导入模块,执行模拟ssc远程控制命令 import hashlib phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('192.168.20.6',8909)) phone.listen(5) print('staring.....') conn,client_addr = phone.accept() while True: username = conn.recv(10240).decode('utf-8') print(username) password = conn.recv(10240).decode('utf-8') print(password) user_md5 = '34d75c9634ae59d1581a5251b981f98c' paw_md5 = '98699a6ffb4200d29ff79e7f0c20a7db' user = hashlib.md5() paw = hashlib.md5() user.update(bytes("szq"+username+"hello",encoding='utf-8')) paw.update(bytes("szq"+password+"hello",encoding='utf-8')) if user.hexdigest()==user_md5 and paw.hexdigest()== paw_md5: conn.send('ok'.encode('utf-8')) 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() else: conn.send('no'.encode('utf-8')) phone.close()
import socket import getpass phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(("192.168.20.6",8909)) for i in range(3): print('用户验证') user = input('admin:').strip() phone.send(user.encode('utf-8')) paw = input('password:').strip() phone.send(paw.encode('utf-8')) data = phone.recv(10240) if data.decode('utf-8') == 'ok': print('login successful') while True: cmd=input('>>>>:').strip() if not cmd:continue phone.send(cmd.encode('utf-8')) cmd_res=phone.recv(10240) print(cmd_res.decode('gbk')) else: print('login failed,您还有{}次机会!'.format(2-i)) phone.close()