making TCP web Server with python - python

I have created a multi threaded python web server and it is working fine for my client server.However i want it to take results work for web server as well. Please help me understand how we do that
the server
import socket
import threading
import os
import sys
#to convert bytes into string
def bytestoString(stringToRead):
stringToRead = bytes.decode(stringToRead)
type(stringToRead)
return(stringToRead)
#to conver string into bytes
def stringToBytes(bytesToSend1):
bytesToSend1= str.encode(bytesToSend1)
type (bytes)
return(bytesToSend1)
#to retreive a file
def retrFile(name,sock):
fileName=sock.recv(1024)
fileName_string = bytestoString(fileName)
print(fileName_string)
stringLength=len(fileName)
fileName_string = bytestoString(fileName[4:(stringLength-8)])
if os.path.isfile(fileName_string):
fileSize=str(os.path.getsize(fileName_string))
fileSize_Bytes = stringToBytes(fileSize)
exists_Bytes=stringToBytes('HTTP/1.1 200 OK')
sock.send(exists_Bytes)
ContentLength_Bytes=stringToBytes('Content-Length:')
sock.send(ContentLength_Bytes+fileSize_Bytes)
userResponse=sock.recv(1024)
userResponse=bytestoString(userResponse)
if userResponse[:2]=='Y':
print ('Ready to send the file................')
with open(fileName_string,'rb') as fileRead:
data= fileRead.read(1024)
sock.send(data)
while data!="":
data=fileRead.read(1024)
sock.send(data)
fileRead.close()
print('xyz')
elif userResponse[:2]=='N':
print('User Terminated file download, Thanks for connecting')
else :
httpResponse=stringToBytes('HTTP/1.1 404 not Found')
sock.send(httpResponse)
sock.close()
def Main(serverPort):
#creating a server socket type TCP
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
localHost=socket.gethostname()
#binding the server to the client
serverSocket.bind((localHost,serverPort))
serverSocket.listen(5)
print ('***Server is ready to recieve***')
while True:
connectionSocket, addr = serverSocket.accept()
print ('got connection from:<', addr,'>')
t=threading.Thread(target=retrFile,args=('retrThread',connectionSocket))
t.start()
connectionSocket.send('thank you for connecting')
connectionSocket.close()
if __name__ == '__main__':
#getting server hostname and port number from the user
serverPort=int(sys.argv[1])
Main(serverPort)
The Client
import sys
import socket
#to convert bytes into string
def bytestoString(stringToRead):
stringToRead = bytes.decode(stringToRead)
type(stringToRead)
return(stringToRead)
#to conver string into bytes
def stringToBytes(bytesToSend):
bytesToSend= str.encode(bytesToSend)
type (bytes)
return(bytesToSend)
#def header():
def Main(serverName,serverPort,fileName_bytes,fileName):
print('***Initialising the socket***')
serverAddress=(serverName,serverPort)
#create the TCP/IP socket using user inout for server and port
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSocket.connect(serverAddress)
httpFileRequest=('GET/'+fileName+' HTTP/1.0')
httpFileRequest=stringToBytes(httpFileRequest)
#Reading the Hostname,socket family, socket type, protocol for the server
connectionDetails= socket.getaddrinfo(serverName,serverPort)
#printing the values to the screen
print (connectionDetails)
#print('Family:',families)
#print('type:',types)
#print('protocol:',protocols)
#Sending the request to recieve the file from the server
if fileName_bytes!="q":
clientSocket.send(httpFileRequest)
serverResponse=clientSocket.recv(1024)
serverResponse_string = bytestoString(serverResponse)
print(serverResponse_string)
fileLength=clientSocket.recv(1024)
fileLength_string = bytestoString(fileLength)
print(fileLength_string)
#checking the server response and downloading the file
if serverResponse_string[13:15]=='OK':
fileSize= float(int(fileLength_string[15:17]))
print(('Size of file you wish to download is:'),fileSize)
clientChoice=input('Please Enter Your Choice (Y/N)?:')
if clientChoice=='Y':
clientChoice=stringToBytes(clientChoice)
clientSocket.send(clientChoice)
#recieveing the file from the server
file = open('new_'+fileName,'wb')
print ('file opened.............')
data=clientSocket.recv(1024)
totalRecv=float(len(data))
file.write(data)
while totalRecv<fileSize:
data=clientSocket.recv(1024)
totalRecv+=len(data)
file.write(data)
percentComplte=int(int((totalRecv)/int(fileSize)*100))
print (('we have completed'),percentComplte,('%'))
file.close()
print ('Download complete')
elif clientChoice=='N':
clientChoice=stringToBytes(clientChoice)
clientSocket.send(clientChoice)
print ('File download terminated')
else :
print ('Please enter the correct choice')
else:
print (serverResponse_string)
clientSocket.close()
#Getting Hostname,socket family, socket type, protocol for the server
def get_constants(prefix):
"""Create a dictionary mapping socket module constants to their names."""
return dict( (getattr(socket, n), n)
for n in dir(socket)
if n.startswith(prefix)
)
#calling main function
if __name__ == '__main__':
#getting server hostname and port number from the user
serverName=sys.argv[1]
serverPort=int(sys.argv[2])
fileName= str(sys.argv[3])
fileName_bytes = str.encode(fileName)
type(bytes)
Main(serverName,serverPort,fileName_bytes,fileName)

Related

Python UDP File Transfer

I'm creating a udp file transfer using python with a client (requests file from server), a server (receives request from client and passes it to the relevant worker) and worker1/worker2 (recieve request from server, if file exists, sends to server to pass back to client) and its all ran in docker containers with an ubuntu image*
Currently, when I type the name of the file I want in the client container, nothing works. I think the file name isn't actually being sent to the server but I can't figure out why at all. I was wondering if anyone can spot my mistake?
Server:
from fileinput import filename
import socket
import time
localIP = "127.0.0.1"
localPort = 50001
bufSize = 1024
msg = "Server is connecting..."
print(msg)
workerAddressPorts = [('127.0.0.1', 50002), ('127.0.0.1', 50003)]
# Create datagram sockets and bind to address and ip
UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPServerSocket.bind((localIP, localPort))
print("Server is waiting for packet...")
while True:
bytesAddressPair = UDPServerSocket.recvfrom(bufSize)
clientBuf = bytesAddressPair[0]
clientAddr = bytesAddressPair[1]
msgFrom = 'Message from Client:{}'.format(clientBuf.decode('utf-8'))
print(msgFrom)
for workerAddressPort in workerAddressPorts:
UDPServerSocket.sendto(clientBuf, workerAddressPort) # send file name to worker
print(f'Clients request has been sent to Worker {workerAddressPort[0]}')
workerBuf = UDPServerSocket.recvfrom(bufSize)[0] # saving data from worker
print(f'Request recieved.')
UDPServerSocket.sendto(workerBuf, clientAddr) # sending data to client
print('Packet from Worker has been sent to Client')
while not workerBuf: # split file to prevent buffer overflow
workerBuf = UDPServerSocket.recvfrom(bufSize)[0]
print(f'Packet received.')
UDPServerSocket.sendto(workerBuf, clientAddr)
print('Packet from worker has been sent to Client')
print('File has been sent to Client.')
Client:
import sys
msgFrom = input('Name of file: ')
print(msgFrom)
bytesToSend = str.encode(msgFrom, 'utf-8')
serverAddressPort = ("127.0.0.1", 50001)
bufSize = 1024
# create UDP Client Socket and send to server
UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPClientSocket.sendto(bytesToSend, serverAddressPort)
while (True):
try:
serverBuf = UDPClientSocket.recvfrom(bufSize)[0]
if len(serverBuf) > 0:
print('Packet incoming...')
msg = serverBuf.decode('utf-8')
if msg == 'NO_FILE':
print('No such file exists.')
break
elif msg == 'END_OF_FILE':
print('Empty file.')
break
else:
f = open(msgFrom, 'wb')
f.write(serverBuf)
f.close()
except Exception as e:
print(e)
Worker:
import socket
import time
from os.path import exists
bufSize = 1024
msg = "Worker is connecting..."
print(msg)
serverAddressPort = ("127.0.0.1", 50001)
# Create a datagram socket and bind to address and ip
UDPWorkerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPWorkerSocket.bind(('127.0.0.1', 50002))
print("Worker is connected and waiting...")
while True:
time.sleep(1)
bytesAddressPair = UDPWorkerSocket.recvfrom(bufSize)
msg = bytesAddressPair[0]
addr = bytesAddressPair[1]
print('Packet Incoming...')
file_name = msg.decode('utf-8')
script_dir = os.path.dirname("C:/Users/Vic/Documents/3rd Year TCD/CSU33031 Computer Networks/Assignments/Assignment1.3/Files to send")
abs_file_path = os.path.join(script_dir, file_name)
if exists(file_name):
f = open(file_name, 'rb')
data = f.read(bufSize)
while data:
if UDPWorkerSocket.sendto(data, serverAddressPort):
data = f.read(bufSize)
time.sleep(1)
print('Sent to Server.')
else:
UDPWorkerSocket.sendto(str.encode('NO_FILE'), serverAddressPort)
print(f'{file_name} was not found. Moving to next available worker..')
Hoping that the for statement in the server, iterates the two worker files(only included one) so if it can't find the file in one worker it moves to the other
*the client is connected to a different network as the two workers. The server is connected to both networks
Thanks in advance!!

send multiple packets of data using python socket programming

So now I have a server and client script. I'm trying to upload a file from the client to the server. However, the data from the file in the client will be cut out by the HEADER size. How do I send multiple packets under the same send command to the server?
server.py:
import socket
import threading
HEADER=2048
PORT=5050
SERVER=socket.gethostbyname(socket.gethostname())
ADDR=(SERVER,PORT)
FORMAT='utf-8'
DISCONNECT_MESSAGE='!DISCONNECT'
SEPARATOR='<SEPERATE>'
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(ADDR)
def handle_client(conn,addr):
print(f'[NEW CONNECTION] {addr} connected.')
connected=True
while connected:
data=conn.recv(HEADER).decode(FORMAT)
if data==DISCONNECT_MESSAGE:
connected=False
else:
data=data.split(SEPARATOR)
file=open(data[0],'w')
file.write(data[1])
print('file received')
conn.send('file received'.encode(FORMAT))
conn.close()
print(f'[DISCONNECT] {addr} disconnected')
def start():
server.listen()
print(f'[LISTENING] Server is listening on {SERVER}')
while True:
conn,addr=server.accept()
thread=threading.Thread(target=handle_client,args=(conn,addr))
thread.start()
print(f'[ACTIVE CONNECTIONS] {threading.activeCount()-1}')
print("[STARTING] server is starting...")
start()
client.py:
import socket
HEADER=2048
PORT=5050
FORMAT='utf-8'
DISCONNECT_MESSAGE='!DISCONNECT'
SEPARATOR='<SEPERATE>'
SERVER=socket.gethostbyname(socket.gethostname())
ADDR=(SERVER,PORT)
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(ADDR)
def send(msg):
message=msg.encode(FORMAT)
client.send(message)
print(client.recv(HEADER).decode(FORMAT))
file=open('question_pool.csv','r')
data=file.read()
send(f'question_pool.csv{SEPARATOR}{data}')
file.close()
send(DISCONNECT_MESSAGE)
In short, you want to send multiple chunks of any file that is larger than your HEADER size. Split the file into chunks smaller than the HEADER size, and send each chunk individually. Then when all the chunks are set, send a message that says the whole file has been sent so that the server can save it.
Here is my code for the solution described above:
server.py:
import socket
import threading
HEADER = 2048
PORT = 5050
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = '!DISCONNECT'
SEPARATOR = '<SEPERATE>'
FILE_FINISHED_SENDING = '<!FILE_SENT!>'
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(ADDR)
def handle_client(conn, addr):
print(f'[NEW CONNECTION] {addr} connected.')
connected = True
current_file = None
while connected:
data = conn.recv(HEADER).decode(FORMAT)
if data == DISCONNECT_MESSAGE:
connected = False
elif data == FILE_FINISHED_SENDING:
current_file.close()
current_file = None
conn.send(b'file received.')
else:
data = data.split(SEPARATOR)
if len(data) == 2 and data[1] == '':
# The name of the file was sent, more will follow.
current_file = open(data[0], 'w')
conn.send(b'filename recieved')
else:
# File data was send, so write it to the current file
current_file.write(data[1])
print('chunk of file recv''d')
conn.send(b'chunk received')
conn.close()
print(f'[DISCONNECT] {addr} disconnected')
def start():
server.listen()
print(f'[LISTENING] Server is listening on {SERVER}')
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn,addr))
thread.start()
print(f'[ACTIVE CONNECTIONS] {threading.activeCount()-1}')
print("[STARTING] server is starting...")
start()
client.py:
import socket
from pathlib import Path
HEADER = 2048
PORT = 5050
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = '!DISCONNECT'
SEPARATOR = '<SEPERATE>'
FILE_FINISHED_SENDING = '<!FILE_SENT!>'
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)
def chunker(string: str, size: int):
return (string[pos:pos + size] for pos in range(0, len(string), size))
def send(msg):
message = msg.encode(FORMAT)
client.send(message)
print(client.recv(HEADER).decode(FORMAT))
def send_file(filepath: str):
with open(filepath, 'r', encoding=FORMAT) as f:
data = f.read()
first_bits = f'{Path(filepath).name}{SEPARATOR}' # Easy way of getting just a file's name from its path
send(first_bits) # Send the filename to the server
for chunk in chunker(data, HEADER-48): # Leave a safe buffer
# Send each chunk of the file
send(f"{SEPARATOR}{chunk}")
# Tell the server that's all for this file.
# Now it can close the file object.
send(FILE_FINISHED_SENDING)
send_file("/path/to/file.html")
send(DISCONNECT_MESSAGE)
Tips:
make sure that your special messages like SEPARATOR, FILE_FINISHED_SENDING and DISCONNECT_MESSAGE are NOT going to appear in the files you are sending. Otherwise things might get wonky.
You may want to read files as raw bytes when you send them through the socket, instead of reading as strings, encoding, decoding, etc. This way you could send binary files such as .mp3, for example.

Python how to use string in multiple scripts

I'm running a python script on a raspberry pi that reads keyboard input to a string and will be sending that string through TCP. I've made two script one that reads the input and one that can send the string if needed. How can i use one string and use it in both scripts for readings and writings?
I've used an text document. Only becaue of the sd card i wanne achieve an connecting between the two scripts
Reading part:
#loops for Barcode_Data
def Create_File():
file = open("Barcode_data.txt", "w")
file.write(" // ")
file.close()
empty = ''
def Barcode_Read():
Barcode_Data= input("Input: ",)
print(Barcode_Data)
file = open("Barcode_data.txt", "a")
file.write(Barcode_Data)
file.write(" // ")
file.close()
#Loop that will only run once
Create_File()
#Loop that will run continuesly
while True:
Barcode_Read()
TCP Server:
#TCP server
def TCP_Connect(socket):
socket.listen()
conn, addr = socket.accept()
with conn:
data = conn.recv(1024)
if data == b'Barcode_Data':
tcp_file = open("Barcode_data.txt", "r")
Barcode_Data = tcp_file.read()
tcp_file.close()
conn.sendall(Barcode_Data.encode('utf-8'))
elif data == b'Clear Barcode_Data':
tcp_file = open("Barcode_data.txt", "w")
tcp_file.write(" // ")
tcp_file.close()
#TCP Socket setup
HOST = '' # Standard loopback interface address (localhost)
PORT = 1025 # Port to listen on (non-privileged ports are > 1023)
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
#Loop that wil run continuesly
while True:
TCP_Connect(s)
You can use the code from this question as is: Interprocess communication in Python
Server process:
from multiprocessing.connection import Listener
address = ('localhost', 6000) # family is deduced to be 'AF_INET'
listener = Listener(address, authkey='secret password')
conn = listener.accept()
print 'connection accepted from', listener.last_accepted
while True:
msg = conn.recv()
# do something with msg
if msg == 'close':
conn.close()
break
listener.close()
Client process:
from multiprocessing.connection import Client
address = ('localhost', 6000)
conn = Client(address, authkey='secret password')
conn.send('close')
# can also send arbitrary objects:
# conn.send(['a', 2.5, None, int, sum])
conn.close()
Documentation is available here: https://docs.python.org/3.7/library/multiprocessing.html#multiprocessing-listeners-clients

Why does the file not transfer completely? Python Socket Programming

The problem I'm having is to get a file from the server. Lets say I want to
"get ./testing.pdf" which sends the pdf from the server to the client. It sends but it is always missing bytes. Is there any problems with how I am sending the data. If so how can I fix it? I left out the code for my other functionalities since they are not used for this function.
server.py
import socket, os, subprocess # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
#host = ''
port = 5000 # Reserve a port for your service.
bufsize = 4096
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
while True:
userInput = c.recv(1024)
.... CODE ABOUT OTHER FUNCTIONALITY
elif userInput.split(" ")[0] == "get":
print "inputed get"
somefile = userInput.split(" ")[1]
size = os.stat(somefile).st_size
print size
c.send(str(size))
bytes = open(somefile).read()
c.send(bytes)
print c.recv(1024)
c.close()
client.py
import socket, os # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
#host = '192.168.0.18'
port = 5000 # Reserve a port for your service.
bufsize = 1
s.connect((host, port))
print s.recv(1024)
print "Welcome to the server :)"
while 1 < 2:
userInput = raw_input()
.... CODE ABOUT OTHER FUNCTIONALITY
elif userInput.split(" ")[0] == "get":
print "inputed get"
s.send(userInput)
fName = os.path.basename(userInput.split(" ")[1])
myfile = open(fName, 'w')
size = s.recv(1024)
size = int(size)
data = ""
while True:
data += s.recv(bufsize)
size -= bufsize
if size < 0: break
print 'writing file .... %d' % size
myfile = open('Testing.pdf', 'w')
myfile.write(data)
myfile.close()
s.send('success')
s.close

python network threading simple chat, waits for user to press enter then gets messages

so right now in order to receive your message you need to receive one
my teachers instructions are (in the main)"Modify the loop so that it only listens for keyboard input and then sends it to the server."
I did the rest but don't understand this, ... help?
import socket
import select
import sys
import threading
'''
Purpose: Driver
parameters: none
returns: none
'''
def main():
host = 'localhost'
port = 5000
size = 1024
#open a socket to the client.
try:
clientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSock.connect((host,port))
#exit on error
except socket.error, (value,message):
if clientSock :
clientSock.close()
print "Could not make connection: " + message
sys.exit(1)
thread1 = ClientThread()
thread1.start()
while True:
#wait for keyboard input
line = raw_input()
#send the input to the server unless its only a newline
if line != "\n":
clientSock.send(line)
#wait to get something from the server and print it
data = clientSock.recv(size)
print data
class ClientThread(threading.Thread):
'''
Purpose: the constructor
parameters: the already created and connected client socket
returns: none
'''
def __init__(self, clientSocket):
super(ClientThread, self).__init__()
self.clientSocket = clientSocket
self.stopped = False
def run(self):
while not self.stopped:
self.data = self.clientSocket.recv(1024)
print self.data
main()
I assume your purpose is to create a program that starts two threads, one (client thread) receives keyboard input and sends to the other (server thread), the server thread prints out everything it received.
Based on my assumption, you first need to start a ServerThread listen to a port (it's not like what your 'ClientThread' did). Here's an example:
import socket
import threading
def main():
host = 'localhost'
port = 5000
size = 1024
thread1 = ServerThread(host, port, size)
thread1.start()
#open a socket for client
try:
clientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSock.connect((host,port))
except socket.error, (value,message):
if clientSock:
clientSock.close()
print "Could not connect to server: " + message
sys.exit(1)
while True:
#wait for keyboard input
line = raw_input()
#send the input to the server unless its only a newline
if line != "\n":
clientSock.send(line)
# Is server supposed to send back any response?
#data = clientSock.recv(size)
#print data
if line == "Quit":
clientSock.close()
break
class ServerThread(threading.Thread):
def __init__(self, host, port, size):
super(ServerThread, self).__init__()
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind((host, port))
self.sock.listen(1)
self.data_size = size
self.stopped = False
def run(self):
conn, addr = self.sock.accept()
print 'Connected by', addr
while not self.stopped:
data = conn.recv(self.data_size)
if data == 'Quit':
print 'Client close the connection'
self.stopped = True
else:
print 'Server received data:', data
# Is server supposed to send back any response?
#conn.sendall('Server received data: ' + data)
conn.close()
if __name__ == '__main__':
main()
And these are the output:
Connected by ('127.0.0.1', 41153)
abc
Server received data: abc
def
Server received data: def
Quit
Client close the connection
You may check here for more details about Python socket: https://docs.python.org/2/library/socket.html?#example

Categories

Resources