socket编程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了socket编程相关的知识,希望对你有一定的参考价值。
一.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.套接字工作流程
二.基于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()
三.粘包
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()
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()
以上是关于socket编程的主要内容,如果未能解决你的问题,请参考以下文章