I'm trying to send and receive files through a TCP socket. When user types put abc.txt, abc.txt should be copied to the server.
When user types get def.txt, def.txt should be downloaded to the user computer. (Actually I have to implement 2 more methods - ls to list all files in the client directory and lls to list all files in the server, but I haven't done it yet.)
Here's the code
Server
import socket
import sys
HOST = 'localhost'
PORT = 3820
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((HOST, PORT))
socket.listen(1)
while (1):
conn, addr = socket.accept()
print 'New client connected ..'
reqCommand = conn.recv(1024)
print 'Client> %s' %(reqCommand)
if (reqCommand == 'quit'):
break
#elif (reqCommand == lls):
#list file in server directory
else:
string = reqCommand.split(' ', 1) #in case of 'put' and 'get' method
reqFile = string[1]
if (string[0] == 'put'):
with open(reqFile, 'wb') as file_to_write:
while True:
data = conn.recv(1024)
if not data:
break
file_to_write.write(data)
file_to_write.close()
break
print 'Receive Successful'
elif (string[0] == 'get'):
with open(reqFile, 'rb') as file_to_send:
for data in file_to_send:
conn.sendall(data)
print 'Send Successful'
conn.close()
socket.close()
Client
import socket
import sys
HOST = 'localhost' #server name goes in here
PORT = 3820
def put(commandName):
socket.send(commandName)
string = commandName.split(' ', 1)
inputFile = string[1]
with open(inputFile, 'rb') as file_to_send:
for data in file_to_send:
socket.sendall(data)
print 'PUT Successful'
return
def get(commandName):
socket.send(commandName)
string = commandName.split(' ', 1)
inputFile = string[1]
with open(inputFile, 'wb') as file_to_write:
while True:
data = socket.recv(1024)
#print data
if not data:
break
print data
file_to_write.write(data)
file_to_write.close()
break
print 'GET Successful'
return
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect((HOST,PORT))
msg = raw_input('Enter your name: ')
while(1):
print 'Instruction'
print '"put [filename]" to send the file the server '
print '"get [filename]" to download the file from the server '
print '"ls" to list all files in this directory'
print '"lls" to list all files in the server'
print '"quit" to exit'
sys.stdout.write ('%s> ' %msg)
inputCommand = sys.stdin.readline().strip()
if (inputCommand == 'quit'):
socket.send('quit')
break
# elif (inputCommand == 'ls')
# elif (inputCommand == 'lls')
else:
string = inputCommand.split(' ', 1)
if (string[0] == 'put'):
put(inputCommand)
elif (string[0] == 'get'):
get(inputCommand)
socket.close()
There are several problems that I couldn't fix.
The program run correctly only on the first time (both 'put' and
'get' method). After that, All commands from the client can't be
sent to the server.
The 'get' method doesn't work for an image/photo file.
First problem is occurring because after handling one command, server is closing the connection.
conn.close()
Second problem is occurring because you are not reading all the data from the socket in client. At the end of while loop you have a "break" statement, due to which client is closing the socket just after reading 1024 bytes. And when server tries to send data on this close socket, its results in error on the server side.
while True:
data = socket1.recv(1024)
# print data
if not data:
break
# print data
file_to_write.write(data)
file_to_write.close()
break
There are two ways to fix this first issue.
Change the client so that for each command it creates a new connection & sends command to the server.
Change the server to handle multiple commands over the same connection.
Following code is the changed client to demonstrate the first way to fix the first issue. It also fixes the second issue.
import socket
import sys
HOST = 'localhost' # server name goes in here
PORT = 3820
def put(commandName):
socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket1.connect((HOST, PORT))
socket1.send(commandName)
string = commandName.split(' ', 1)
inputFile = string[1]
with open(inputFile, 'rb') as file_to_send:
for data in file_to_send:
socket1.sendall(data)
print 'PUT Successful'
socket1.close()
return
def get(commandName):
socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket1.connect((HOST, PORT))
socket1.send(commandName)
string = commandName.split(' ', 1)
inputFile = string[1]
with open(inputFile, 'wb') as file_to_write:
while True:
data = socket1.recv(1024)
# print data
if not data:
break
# print data
file_to_write.write(data)
file_to_write.close()
print 'GET Successful'
socket1.close()
return
msg = raw_input('Enter your name: ')
while(1):
print 'Instruction'
print '"put [filename]" to send the file the server '
print '"get [filename]" to download the file from the server '
print '"ls" to list all files in this directory'
print '"lls" to list all files in the server'
print '"quit" to exit'
sys.stdout.write('%s> ' % msg)
inputCommand = sys.stdin.readline().strip()
if (inputCommand == 'quit'):
socket.send('quit')
break
# elif (inputCommand == 'ls')
# elif (inputCommand == 'lls')
else:
string = inputCommand.split(' ', 1)
if (string[0] == 'put'):
put(inputCommand)
elif (string[0] == 'get'):
get(inputCommand)
Related
So for some reason this code is not properly working for sending a zip folder from the client to server. on the server side if I use "f = zipfile.ZipFile("platformIO.zip")" I get the error "ValueError: stat: embedded null character in path", and if I use "f = open("platformIO.zip", "wb")" no error is thrown but the received file is corrupt and won't open.
I have read every similar to question to this and cannot find a solution.
Client:
import socket
import time
# Configure wireless connection with server (board on leg)
HOST = "192.168.4.1" # change to server ip address
PORT = 5005 # must be same as server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
print("connected")
user_input = "startup"
while True:
if user_input == "startup":
# ask if user wants to send code
user_input = input("Do you want to send new code?: (y/n)")
if user_input == "y":
user_input = "send code"
elif user_input == "n":
user_input = input("Would you like to collect data?: (y/n)")
if user_input == "y":
user_input = "receive data"
else:
user_input = "startup"
else:
user_input == "startup"
elif user_input == "send code":
st = "sending code"
s.send(st.encode())
file = "platformIO.zip"
try:
with open(file, "rb") as f:
print("sending file...")
data = f.read()
s.sendall(data)
print("finished sending")
st = "finished"
s.send(st.encode())
user_input = "startup"
except:
print("Failed transfering <platformIO.zip>, make sure it exists")
st = "failed"
s.send(st.encode())
elif input =="receive data":
print("feature not yet implemented")
user_input == "startup"
# delay
time.sleep(0.1)
Server:
import socket
import time
import zipfile
import os
# create server
HOST = "192.168.4.1"
PORT = 5005
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("socket created")
# managing error exception
try:
s.bind((HOST,PORT))
except socket.error:
print("bind Failed")
s.listen(1)
print("Socket awaiting mesesages")
(conn, addr) = s.accept()
print("connected")
# awaiting message
msg = "startup"
while True:
if msg == "startup":
# receive data from controller
msg = conn.recv(4096)
print(str(msg, 'utf-8'))
elif str(msg, 'utf-8') == "sending code":
f = zipfile.ZipFile("platformIO.zip", "w")
#f = open("platformIO.zip", "wb")
while True:
data = conn.recv(4096)
print(data)
if not data:
break
f.write(data)
print("file received")
msg = "startup"
time.sleep(.1)
conn.close()
edit: if I use f = open("platformIO.zip", "wb") and add s.close() inside the writing while loop of the server, I can receive the zip successfully, but then the connection closes and I can't open the zip file until I close the program
f = open("platformIO.zip", "wb")
while True:
data = conn.recv(4096)
print(data)
if not data:
break
f.write(data)
s.close()
Started to implement this project in C++, however I figured Python would be a better choice going forward for x-platform.
Goal here is to create a simple file server and then create a client. Client should be able to upload files to the server and download files from the server.
My code for the client is:
import socket
def Main():
host = '127.0.0.1'
port = 5000
s = socket.socket()
s.connect((host,port))
choice = raw_input("Upload or Download? (u/d):")
if choice == 'd':
filename = raw_input("File to Download? (q to quit): ")
if filename != 'q':
s.send(filename)
data = s.recv(1024)
if data[:6] == "EXISTS":
filesize = long(data[6:])
message = raw_input("File found on the server!," +str(filesize)+"bytes, continue with download? y/n:")
if message == "y":
s.send('OK')
f = open('new_'+filename, 'wb')
data = s.recv(1024)
totalRecv = len(data)
f.write(data)
while totalRecv < filesize:
data = s.recv(1024)
totalRecv += len(data)
f.write(data)
print ("Percentage Completed: "+"{0:.2f}".format((totalRecv/float(filesize))*100))
print ("File has been Downloaded!")
else:
print ("File doesnt exist!")
else:
filename = raw_input("File to Upload? (q to quit): ")
# if filename != 'q':
print ("Upload Function Coming Soon")
s.close()
if __name__ == '__main__':
Main()
The code for the server is:
import socket
import threading
import os
def RetrFile(name, sock):
filename = sock.recv(1024)
if os.path.isfile(filename):
sock.send("EXISTS" + str(os.path.getsize(filename)))
userResponse = sock.recv(1024)
if userResponse[:2] == 'OK':
with open(filename, 'rb') as f:
bytesToSend = f.read(1024)
sock.send(bytesToSend)
while bytesToSend != "":
bytesToSend = f.read(1024)
sock.send(bytesToSend)
else:
sock.send("ERR")
sock.close()
def Main():
host = "127.0.0.1"
port = 5000
s = socket.socket()
s.bind((host,port))
s.listen(5)
print ("Server Started")
while True:
c, addr = s.accept()
print ("Client Connected:") + str(addr) + ">"
t = threading.Thread(target=RetrFile, args=("retrThread", c))
t.start()
s.close()
if __name__ == '__main__':
Main()
I have it just fine for the download of the file, and thinking about it, I should be able to just reverse process for the upload portion of the client (instead of fetch the download, I basically copy the server part to perform the upload)...however I just cant seem to wrap my head around how to do so. I'm not worried at this point over the hard coded port etc---will fix that later, however does anyone have any suggestions going forward with this?
I need to emphasize that I am using python < v3 (I know--its old) however its a program limitation that I need to adhere to (hence the raw_input() v. input())
Here is my server.py:
import socket, atexit
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((socket.gethostname(), 8000))
server.listen(5)
(client,(ip,port))=server.accept()
command = raw_input('> ')
if command.rsplit(' ',1)[0] == 'write':
client.send(command.rsplit(' ',1)[2])
print 'Client # ', ip + ' '
data = client.recv(1024)
file = open(command.rsplit(' ',1)[1],'rb')
bytes = file.read(1024)
while(bytes):
client.send(bytes)
bytes = file.read(1024)
file.close()
client.close()
The client.py:
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('MY IP', 8000))
client.send("!")
name = client.recv(1024)
with open(name, 'wb') as file:
while True:
data = client.recv(1024)
if not data:
break
file.write(data)
file.close()
client.close()
The first data transmission in server.py is supposed to send the name of the file I want to the client.py. Where it says:
name = client.recv(1024)
in client.py, it is supposed to receive and make a file using that name. However, the server.py closes, causing the client.py to crash and not give output (host closed). If I open in IDLE to see the output, it doesn't work but nothing shows.
Your server.py needed tweaked;
import socket, atexit
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 8000))
server.listen(5)
(client,(ip,port))=server.accept()
command = raw_input('> ')
if command.split(' ')[0] == 'write':
client.send(command.split(' ')[2])
print 'Client # '+str(ip)+':'
data = client.recv(1024)
file = open(command.split(' ')[1],'rb')
bytes = file.read(1024)
while(bytes):
client.send(bytes)
bytes = file.read(1024)
file.close()
client.close()
The rsplit and trailing ,1's were causing the breaks.
Using the input write /Users/Namelessthehckr/Downloads/ucsgflmza.cs /Users/Namelessthehckr/Desktop/Test.txt, the file was successfully CP'd without error.
I'm trying to print the contents of a file to the client using the defined command 'get'. I am not getting the contents of the file instead the contents are getting over written with Server Says... get test.txt.
Here is my client code:
import socket
import sys
import os
HOST = 'localhost'
PORT = 8082
size = 1024
def ls():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
s.send(userInput)
result = s.recv(size)
print result
s.close()
return
def put(commandName):
socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket1.connect((HOST, PORT))
socket1.send(commandName)
string = commandName.split(' ', 1)
inputFile = string[1]
with open(inputFile, 'rb') as file_to_send:
for data in file_to_send:
socket1.sendall(data)
print 'PUT Successful'
socket1.close()
return
def get(commandName):
socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket1.connect((HOST, PORT))
socket1.send(commandName)
string = commandName.split(' ', 1)
inputFile = string[1]
with open(inputFile, 'wb') as file_to_write:
while True:
data = socket1.recv(1024)
print data
if not data:
break
print data
file_to_write.write(data)
file_to_write.close()
print 'GET Successful'
#socket1.close()
return
done = False
while not done:
userInput = raw_input()
if "quit" == userInput:
done = True
elif "ls" == userInput:
ls()
else:
string = userInput.split(' ', 1)
if (string[0] == 'put'):
put(userInput)
elif (string[0] == 'get'):
get(userInput)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
s.send(userInput)
data = s.recv(size)
s.close()
print 'Received:', data
And server code:
import socket
import os
import sys
host = ''
port = 8082
backlog = 5
size = 1024
serverID = socket.gethostbyname(socket.gethostname())
info = 'SERVER ID: {} port: {}'.format(serverID, port)
print info
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
done = False
# Loop until client sends 'quit' to server
while not done:
client, address = s.accept()
data = client.recv(size)
print "Server received: ", data
if data:
client.send("Server Says... " + data)
if data == "quit":
done = True
elif data == "ls":
data = os.listdir("C://")
client.send(data[0])
else:
string = data.split(' ', 1)
dataFile = string[1]
if (string[0] == 'put'):
with open(dataFile, 'wb') as file_to_write:
while True:
data = client.recv(1024)
if not data:
break
file_to_write.write(data)
file_to_write.close()
break
print 'Receive Successful'
elif (string[0] == 'get'):
with open(dataFile, 'rb') as file_to_send:
for data in file_to_send:
client.send(data)
print 'Send Successful'
client.close()
s.close()
print "Server exiting."
You are getting the content of the file but it is empty... and your code works just because you probably run it in the same directory.
Your client open file to write (and then it is empty) and the server reads it (both code use the same file name). You probably wanted to read file from C:\ so you should change server code and replace line:
with open(dataFile, 'rb') as file_to_send:
with:
with open('C:\\' + dataFile, 'rb') as file_to_send:
No matter what you send to the server this condition is true so you get "server says..."
if data:
client.send("Server Says... " + data)
You have also several flaws in you client I think. Like your commands are sent 2 times: once in the client 'main' when you do:
s.send(userInput)
And once in the functions like get and ls :
socket1.send(commandName)
I'd like to let more than one client connect to my server, and have the server send them different items. For example send "hi" to the first client and "goodbye" to the second . Here's my code:
Server
import socket
file_num = 0
inp = raw_input("Name of the wordlist file = ")
inp2 = input("Number of lines for every wordlist = ")
with open(inp) as in_file:
for line_num, line in enumerate(in_file):
print line_num
if not line_num % inp2:
file_num += 1
with open("out{0}.txt".format(file_num), "a") as out_file:
out_file.writelines(line)
def upload(host, port):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((host, port))
server_socket.listen(5)
filename = open("out1.txt", "rb")
print "Server Waiting for client on port ", port
while 1:
client_socket, address = server_socket.accept()
print "Connection from ", address
while 1:
for line in filename:
server_data = line
if server_data.lower() == 'q':
client_socket.send(server_data)
client_socket.close()
break
else:
client_socket.send(server_data)
client_data = client_socket.recv(1024)
if client_data.lower() == 'q':
print "Quit from client"
client_socket.close()
break
else:
print "<-- client: ", client_data
break
upload("localhost", 4000)
and then my client program
Client
import socket
port = 4000
host_server = "localhost"
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((host_server, port))
z = 1
print "Type 'Q' or 'q' to QUIT"
f = open("pino.txt", "w")
while 1:
server_data = client_socket.recv(1024)
f.writelines(server_data)
if server_data.lower() == 'q':
print "Quit from server"
client_socket.close()
break
else:
print "<-- server: ", server_data
client_data = ("Sent "+str(z))
z = z+1
if client_data.lower() != 'q':
client_socket.send(client_data)
else:
client_socket.send(client_data)
client_socket.close()
break
f.close()
Hope you give me the solution cause this will be cool if it works, another thing I'd like for this program is if the filename under def upload would change for every client. For example the first client will get out1 and the 7th will get out7. Thanks in advance.
P.S. I'm new to python so if you could explain me what you changed it would be great, don't ask me to use Twisted cause Id like to do this with the normal python socket .
I've had this problem myself :-)
So what you're trying to do is have multiple connections, however usually socket uses the main thread, making it hard to have more than one connection.
To fix this we need to use something called Threading, it allows you to surpass operations onto other threads. So you need to create a new thread when every connection is made:
import socket
from _thread import *
file_num = 0
inp = raw_input("Name of the wordlist file = ")
inp2 = input("Number of lines for every wordlist = ")
with open(inp) as in_file:
for line_num, line in enumerate(in_file):
print line_num
if not line_num % inp2:
file_num += 1
with open("out{0}.txt".format(file_num), "a") as out_file:
out_file.writelines(line)
def upload(host, port):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((host, port))
server_socket.listen(5)
filename = open("out1.txt", "rb")
print "Server Waiting for client on port ", port
while 1:
client_socket, address = server_socket.accept()
print "Connection from ", address
while 1:
for line in filename:
server_data = line
if server_data.lower() == 'q':
client_socket.send(server_data)
client_socket.close()
break
else:
client_socket.send(server_data)
client_data = client_socket.recv(1024)
if client_data.lower() == 'q':
print "Quit from client"
client_socket.close()
break
else:
print "<-- client: ", client_data
break
start_new_thread(upload, ("localhost", 4000))
#NOTICE!!! If this line doesn't work ^^^
#Then replace it with:
#thread.start_new_thread(upload, ("localhost", 4000))
Hope this helps! :-)
Please tell me if it doesn't,
for I have not tested this, I've just done it before :)
Thanks,
~Coolq