使用Python套接字发送和接收
我现在正在尝试写一个程序,这个程序可以把一串IP地址嵌入到数据包中,然后发送到多个服务器。每个服务器会去掉最外层的IP地址,然后把数据包转发到指定的IP。这就像我们所说的“隧道”技术。在这个过程中,我还希望服务器能对转发的数据包进行一次“ traceroute”,然后把结果发回给前一个服务器。
我现在的代码可以转发数据包,但在执行“traceroute”时卡住了,无法获取结果。我觉得问题出在中间服务器的一个循环里,可能是因为我没有正确关闭套接字。你有什么建议吗?
客户端
#!/usr/bin/env python
import socket # Import socket module
import sys
import os
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 17353 # Reserve a port
FILE = raw_input("Enter filename: \n ")
NIP = raw_input("Enter Number of IPs: ")
accepted_IP = 0
IP= []
while accepted_IP < int(NIP):
IP.append(raw_input("Enter destination IP: \n"))
accepted_IP +=1
#cIP = raw_input("Enter intemediate IP: \n ")
ipv = raw_input("Enter IP version... 4/6")
try:
s.connect((host, port))
print "Connection sucessful!"
except socket.error as err:
print "Connection failed. Error: %s" %err
quit()
raw = open(FILE,"rb")
size = os.stat(FILE).st_size
ls = ""
buf = 0
for i in IP:
while len(i) < 15:
i += "$"
ls += i
header = ipv+NIP+ls+FILE
print ls
s.sendall(header + "\n")
print "Sent header"
data = raw.read(56) +ipv + NIP + ls
print "Begin sending file"
while buf <= size:
s.send(data)
print data
buf += 56
data = raw.read(56) + ipv + NIP + ls
raw.close()
print "Begin receiving traceroute"
with open("trace_log.txt","w") as tracert:
trace = s.recv(1024)
while trace:
treacert.write(trace)
if not trace: break
trace = s.recv(1024)
print "finished forwarding"
s.close()
中间服务器
#!/usr/bin/env python
import socket
import subprocess
srvsock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
srvsock.bind( (socket.gethostname(), 17353) )
srvsock.listen( 5 ) # Begin listening with backlog of 5
# Run server
while True:
clisock, (remhost, remport) = srvsock.accept() #Accept connection
print
d = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
header = ""
while True:
b = clisock.recv(1)
if b == "\n":
break
header += b
num = 15 * int(header[1]) + 2
file_name = header[num:]
nheader = header[0]+ str(int(header[1])-1) + header[17:]
d.connect((socket.gethostname(), 12355))
d.sendall(nheader+'\n')
print "begin forwarding"
while True:
raw = clisock.recv(56 + num) # recieve data
ip = raw[-15:] # extract IP
ipv, NIP = raw[57] , str(int(raw[57])-1)
if NIP == "0":
while (raw):
print "stuck in this loop"
d.send(raw[:56])
raw=clisock.recv(56+num)
if not raw: break
else:
while (raw):
print raw[:57] + NIP + raw[59:-15]
print "\n"
d.send(raw[:57] + NIP + raw[59:-15])
raw = clisock.recv(56+num)
if not raw :break
print "Finish forwarding"
d.close()
break
print "Begin traceroute"
tracrt = subprocess.Popen(['traceroute','google.com'], stdout=subprocess.PIPE)
s.sendall(tracrt.communicate()[0])
print "Finished"
clisock.close()
s.close()
目标服务器
import socket
s = socket.socket()
host = socket.gethostname()
port = 12355
s.bind((host,port))
s.listen(5)
while True:
csock, (client, cport) = s.accept()
print client
header = ""
while True:
b = csock.recv(1)
if b == "\n":
break
header += b
file_name = header[2:]
r = open("File_test_"+file_name,"wb")
print 'Opening file for writing'
while True:
print "Begin writing file" + " " + file_name
raw = csock.recv(56)
while (raw):
print raw
r.write(raw)
raw = csock.recv(56)
r.flush()
r.close()
print "finish writing"
break
print "closing connection"
csock.close()
s.close()
1 个回答
0
中间服务器在这个循环中卡住了,因为它在执行clisock.recv()
时,退出的条件not raw
没有在客户端关闭连接之前满足。而且,客户端在接收到中间服务器的traceroute之前并没有关闭连接,所以它们就互相等待。
为了解决这个问题,你可以考虑把文件大小发送给中间服务器,这样它就可以用这个信息来判断接收循环什么时候结束。或者,如果你的平台支持关闭连接的一部分,你可以在客户端发送完文件后使用
s.shutdown(socket.SHUT_WR)
来关闭连接。