socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口,把复杂的TCP/IP协议族隐藏在socket接口后面,一组简单的接口就是全部,让socket去组织数据,以符合指定的协议。
套接字有两种:
基于文件类型的套接字家族:AF_UNIX
基于网络类型的套接字家族:AF_INET
#服务器端
import socket
server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)#AF_INET是基于网络的套接字,STREAM是TCP是面向流
ip_port=("10.171.24.42",8001)
buffer_size=1024#最大接受的字节信息
back_log=5#最大挂起的链接数
server.bind(ip_port)#绑定
server.listen(back_log)
conn,addr=server.accept()#阻塞直到有链接进来
data=conn.recv(buffer_size)#接收信息
print("recv:",data.decode())
conn.send('ok'.encode("utf-8"))#发送信息
conn.close()#关闭连接
server.close()#关闭
#客户端
import socket
client=socket.socket(socket.AF_INET, socket.SOCK_STREAM)#AF_INET是基于网络的套接字,STREAM是TCP是面向流
ip_port=("10.171.24.42",8001)
buffer_size=1024#最大接受的字节信息
back_log=5#最大挂起的链接数
client.connect(ip_port)
client.send("hello".encode('utf-8'))
data=client.recv(buffer_size)#接收信息
print("recv:",data.decode())
client.close()#关闭
要是出现Adress已被占用的错误,就在服务器端bind前加上
server.setsockopt(sol_SOCKET,SO_REUSEADDR,1)
#服务器端
import socket
server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)#AF_INET是基于网络的套接字,STREAM是TCP是面向流
ip_port=("10.171.24.42",8000)
buffer_size=1024#最大接受的字节信息
back_log=5#最大挂起的链接数
server.bind(ip_port)#绑定
server.listen(back_log)
while True:
conn,addr=server.accept()#阻塞直到有链接进来
while True:
data=conn.recv(buffer_size)#接收信息
print("recv:",data.decode())
conn.send('ok'.encode("utf-8"))#发送信息
conn.close()#关闭连接
server.close()#关闭
#客户端
import socket
client=socket.socket(socket.AF_INET, socket.SOCK_STREAM)#AF_INET是基于网络的套接字,STREAM是TCP是面向流
ip_port=("10.171.24.42",8000)
buffer_size=1024#最大接受的字节信息
back_log=5#最大挂起的链接数
client.connect(ip_port)
while True:
msg=input(">>:").strip()
client.send(msg.encode('utf-8'))
data=client.recv(buffer_size)#接收信息
print("recv:",data.decode())
client.close()#关闭
#服务器端
"""基于tcp实现远程执行命令"""
import socket
import subprocess
tcp_server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)#AF_INET是基于网络的套接字,STREAM是TCP是面向流
ip_port=("10.171.24.42",8002)
buffer_size=1024#最大接受的字节信息
back_log=5#最大挂起的链接数
tcp_server.bind(ip_port)#绑定
tcp_server.listen(back_log)
while True:
conn,addr=tcp_server.accept()#阻塞直到有链接进来
while True:
try: #try ...except 是因为基于tcp的套接字不能处理空,udp可以
cmd=conn.recv(buffer_size)#接收信息
print("recv cmd:",cmd.decode())
res=subprocess.Popen(cmd.decode("utf-8"),shell=True,stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE )
err=res.stderr.read()#看有没有出错
if err:#如果出错了,返回错误
cmd_res=err
else:#没出错返回执行结果
cmd_res=res.stdout.read()
if not cmd_res:#如果那种没有返回值的命令,如ls...就返回‘执行成功’
cmd_res="执行成功!".encode("utf-8")
conn.send(cmd_res.encode("gbk"))#发送信息 #这里是gbk,因为是用的subprocess
except Exception as ee:
print(ee)
break
conn.close()#关闭连接
tcp_server.close()#关闭
#客户端
"""基于tcp的套接字socket实现远程执行命令"""
import socket
tcp_client=socket.socket(socket.AF_INET, socket.SOCK_STREAM)#AF_INET是基于网络的套接字,STREAM是TCP是面向流
ip_port=("10.171.24.42",8002)
buffer_size=1024#最大接受的字节信息
back_log=5#最大挂起的链接数
tcp_client.connect(ip_port)
while True:
cmd=input(">>:").strip()
if not cmd:continue
if cmd=="quit":break
tcp_client.send(cmd.encode('utf-8'))
cmd_res=tcp_client.recv(buffer_size)#接收信息
print("执行结果是:",cmd_res.decode("gbk"))
tcp_client.close()#关闭
服务器端的try...except是因为基于tcp的recv在自己这端缓冲区为空时阻塞
UDP相对于TCP,它服务器端减少了listen()和accept(),并且TCP中是SOCK_STREAM,而UDP中是SOCK_DGRAM。
由于没有建立连接,所以接收消息时要加上地址addr,发送的时候后边要加上ip_port
注意,UDP的socket中是sendto和recvfrom
#服务器端
import socket
udp_server=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#AF_INET是基于网络的套接字,STREAM是TCP是面向流
ip_port=("10.171.24.42",8003)
buffer_size=1024#最大接受的字节信息
back_log=5#最大挂起的链接数
udp_server.bind(ip_port)#绑定
while True:
data,addr=udp_server.recvfrom(buffer_size)#接收信息
print("recv:",data.decode("utf-8"))
udp_server.sendto('ok'.encode("utf-8"),addr)#发送信息
server.close()#关闭
#客户端
import socket
udp_client=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#AF_INET是基于网络的套接字,STREAM是TCP是面向流
ip_port=("10.171.24.42",8003)
buffer_size=1024#最大接受的字节信息
back_log=5#最大挂起的链接数
while True:
msg=input(">>:").strip()
udp_client.sendto(msg.encode('utf-8'),ip_port)
data=udp_client.recvfrom(buffer_size)#接收信息
print("recv:", data.decode("utf-8"))
client.close()#关闭
#服务器端
import socket
import subprocess
udp_server=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#AF_INET是基于网络的套接字,STREAM是TCP是面向流
ip_port=("10.171.24.42",8002)
buffer_size=1024#最大接受的字节信息
back_log=5#最大挂起的链接数
udp_server.bind(ip_port)#绑定
while True:
cmd,addr=udp_server.recvfrom(buffer_size)#阻塞直到有链接进来
res=subprocess.Popen(cmd.decode("utf-8"),shell=True,stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE )
err=res.stderr.read()#看有没有出错
if err:#如果出错了,返回错误
cmd_res=err
else:#没出错返回执行结果
cmd_res=res.stdout.read()
if not cmd_res:#如果那种没有返回值的命令,如ls...就返回‘执行成功’
cmd_res="执行成功!".encode("gbk")
udp_server.sendto(cmd_res,addr)#发送信息 #这里是gbk,因为是用的subprocess
udp_server.close()#关闭
#客户端
import socket
udp_client=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#AF_INET是基于网络的套接字,STREAM是TCP是面向流
ip_port=("10.171.24.42",8002)
buffer_size=1024#最大接受的字节信息
back_log=5#最大挂起的链接数
while True:
cmd=input(">>:").strip()
if not cmd:continue
if cmd=="quit":break
udp_client.sendto(cmd.encode('utf-8'),ip_port)
cmd_res,addr=udp_client.recvfrom(buffer_size)#接收信息
print("执行结果是:",cmd_res.decode("gbk"),end='')
udp_client.close()#关闭
YCP