I wanted to create a software that can send video through socket programming. I can send 1 video at a time but when I want to send more than 2, it is stuck.
Below is the server code:
import socket
import os
IP = "127.0.0.1"
PORT = 4456
SIZE = 1024
FORMAT = "utf"
SERVER_FOLDER = "video_folder"
def main():
print("[STARTING] Server is starting.\n")
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((IP, PORT))
server.listen()
print("[LISTENING] Server is waiting for clients.")
conn, addr = server.accept()
print(f"[NEW CONNECTION] {addr} connected.\n")
""" Receiving the folder_name """
folder_name = conn.recv(SIZE).decode(FORMAT)
""" Creating the folder """
folder_path = os.path.join(SERVER_FOLDER, folder_name)
if not os.path.exists(folder_path):
os.makedirs(folder_path)
conn.send(f"Folder ({folder_name}) created.".encode(FORMAT))
else:
conn.send(f"Folder ({folder_name}) already exists.".encode(FORMAT))
""" Receiving files """
while True:
msg = conn.recv(SIZE).decode(FORMAT)
""" Recv the file name """
print(f"[CLIENT] Received the filename: {msg}.")
file_path = os.path.join(folder_path, msg)
file = open(file_path, "wb")
conn.send(f"{file_path} filename received.".encode(FORMAT))
while True:
msg = conn.recv(SIZE) # it stuck here once the msg become nothing need help
if not msg:
conn.send("The data is saved.".encode(FORMAT))
break
file.write(msg)
print('.', end='', flush=True)
if not msg: break
file.close()
print("\ndone.")
def test():
while True:
x = "World"
print("morning")
while True:
print("Hello" + x)
break
if __name__ == "__main__":
main()
Below is the client code:
import socket
import os
IP = "127.0.0.1"
PORT = 4456
SIZE = 1024
FORMAT = "utf"
CLIENT_FOLDER = "C:/Users/wende/OneDrive/Desktop/client_folder"
def main():
""" Staring a TCP socket. """
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((IP, PORT))
""" Folder path """
path = os.path.join(CLIENT_FOLDER, "files")
folder_name = path.split("/")[-1]
""" Sending the folder name """
msg = f"{folder_name}"
print(f"[CLIENT] Sending folder name: {folder_name}")
client.send(msg.encode(FORMAT))
""" Receiving the reply from the server """
msg = client.recv(SIZE).decode(FORMAT)
print(f"[SERVER] {msg}\n")
""" Sending files """
files = sorted(os.listdir(path))
for file_name in files:
""" Send the file name """
print(f"[CLIENT] Sending file name: {file_name}")
client.send(file_name.encode(FORMAT))
""" Recv the reply from the server """
msg = client.recv(SIZE).decode(FORMAT)
print(f"[SERVER] {msg}")
""" Send the data """
file = open(os.path.join(path, file_name), "rb")
file_data = file.read()
client.send(file_data)
print("Sending File...")
msg = client.recv(SIZE).decode(FORMAT)
print(f"[SERVER] {msg}")
if __name__ == "__main__":
main()
I have found out where the code is stuck, but I have no idea why it pauses there for no reason.
The problem I found is I keep loop the received at the server and once the received part is NULL then the loop will stop, but the problem I faced is once the received part is NULL, it cannot jump to the next if statement to check. I try transfer 1 video is no problem at all.
How can I solve this?
The solution is here: Sending a file over TCP sockets in Python
You need to put this line in the client code
client.shutdown(socket.SHUT_WR)
after
client.send(file_data)
IMO: Better to use async / await words to do your chat asynchronously. In current realization when you receive one message from a first client the second going to wait until the first will finish.
I think it will help you Simplest async/await example possible in Python
Related
The idea is to create a server for sending and receiving files for backup, right now the server receives 1 msg from a client in python and another in C++, the problem is, the python client manages to send 1 string and then the server kinda looks, and I have to end the connection, that's for the python client, when I'm trying to send data from the c++ client i got nothing
I'm using Websockets, but my problem seems to be on the try: statement, honestly cant figure it out wheres my problem
sidenote: I'm using quit() to stop my program, but every time I used it I got way too many errors so I had to comment it
Here's my Server.py code
import asyncio
import websockets
import socket
import sqlite3
import sys
def get_ip(): # returns primary private IP only
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# doesn't even have to be reachable
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except Exception:
IP = '127.0.0.1'
finally:
s.close()
return IP
async def handle_connectio(websocket, path): # recive and handle connection from client, would handle json or file data
while True:
try:
async for name in websocket:
#name = await websocket.recv()
print(f"<<< {name}")
#break
except websockets.exceptions.ConnectionClosed:
print (f"Coneecion terminada")
#quit()
break
else:
print (f"algo paso")
#quit()
break
print ("Iniciando el Server webSocket")
print ("Current Ip: " + get_ip())
servidor = websockets.serve(handle_connectio, get_ip(), 8000)
#loop = asyncio.get_event_loop()
#loop.run_until_complete(servidor)
asyncio.get_event_loop().run_until_complete(servidor)
asyncio.get_event_loop().run_forever()
#async def main(): # main function
# print ("Iniciando Server websocket")
# print("Current Ip: " + get_ip())
# async with websockets.serve(handle_connectio, get_ip(), 8000):
# await asyncio.Future()
#if __name__ == '__main__':
# asyncio.run(main())
edit: I did try to simplify my code and it manages to receive the msg and show when the connection is closed - still the main problem persists.
async def handle_connectio(websocket, path): # recive and handle connection from client, would handle json or file data
try:
while True:
#async for data in websocket:
data = await websocket.recv()
print(f"<<< {data}")
await asyncio.sleep(1)
except websockets.exceptions.ConnectionClosed:
print (f"Coneecion terminada")
edit2: heres my client code, if this donst work i would switch to sockets
import asyncio
import websockets
async def client():
direc = "ws://192.168.1.69:8000"
async with websockets.connect(direc) as web:
while True:
nombre = input("Introduce el mensaje >>> ")
await web.send(nombre)
asyncio.get_event_loop().run_until_complete(client())
From looking at and running the example code at https://websockets.readthedocs.io/en/stable/, it's apparent that your connection handler shouldn't loop forever (while True:) but exit after handling all the messages supplied by the websocket. It will be called again when another message arrives.
Edit:
The original server code works fine. The problem is that the client is using the input() function, which blocks asyncio from running, which prevents websocket protocol from running correctly and blocks messages from sending. A small delay after send (await asyncio.sleep(1)) works, although ideally the input() and the asyncio comm logic would be separated, to avoid an arbitrary delay.
Ok for some odd reason websockets wont work/behave properly so i had to switch to Sockets and now i can send the data back and forth, i would post my client and server code for anyone on the future.
Server.py
import socket
# socket.SOCK_STREAM -> TCP
# socket.SOCK_DGRAM -> UDP
def get_ip(): # returns primary private IP only
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# doesn't even have to be reachable
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except Exception:
IP = '127.0.0.1'
finally:
s.close()
return IP
def servidor():
print (f"Iniciando el Servidor Sockets")
print (f"Current IP Addres: " + get_ip())
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((get_ip(), 8000))
server.listen(1)
conn, address = server.accept() # Accept the Client connection
while True:
#1024 is the bandwidth bits
try:
msg = conn.recv(1024).decode() # Recive the msg and trasform it from Binary to String
print("<<< " + msg)
except:
print (f"coneccion terminada")
break
if __name__ == "__main__":
servidor()
Client.py
import socket
print ('Iniciando cliente')
conn_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
conn_client.connect( ('192.168.1.68', 8000))
while True:
try:
msg = (f">>> ")
conn_client.sendall(msg.encode())
except:
print (f"Connection Close")
break
#recibido = conn_client.recv(1024)
#print (recibido.decode())
conn_client.close()
server.py:
json files from NVD are used here
import socket, json, random, threading, zipfile, requests, re, zipfile
from bs4 import BeautifulSoup
from zipfile import *
def listen_user(user):
for x in range(2018,2021,1):
filename = "nvdcve-1.1-" + str(x) + ".json"
print(filename)
with open(filename, 'rb') as file:
sendfile = file.read()
user.sendall(sendfile)
print('file sent' + str(x))
def start_server():
while True:
user_socket, address = server.accept()
print(f"User <{address[0]}> connected!")
users.append(user_socket)
listen_accepted_user = threading.Thread(
target=listen_user,
args=(user_socket,)
)
listen_accepted_user.start()
if __name__ == '__main__':
users = []
server = socket.socket(
socket.AF_INET,
socket.SOCK_STREAM,
)
server.bind(
("127.0.0.1", 100)
)
server.listen(5)
print('waiting for connection...')
start_server()
client.py
import socket, json, random
from threading import Thread
def start_client(client):
savefilename = str(random.randint(1,10)) + 'new.json'
print(savefilename)
with client,open(savefilename,'wb') as file:
while True:
recvfile = client.recv(4096)
if not recvfile:
print('1 client')
break
file.write(recvfile)
file.close()
print('2 client')
client.close()
if __name__ == '__main__':
client = socket.socket(
socket.AF_INET,
socket.SOCK_STREAM,
)
client.connect(
("127.0.0.1", 100)
)
start_client(client)
when I send files - they are sent almost in full, but the program does not reach the line "print ('1 client')" or "print ('2 client')"
and the *new file contains all lines except a few dozen of the last
please help - how to fix the code?
recvfile = client.recv(4096) is inside the while loop and it is continuously waiting for the next bytes to receive. The client doesn't know the files are sent, so it waits for the next 4096 bytes and doesn't exit the loop.
To let the client know that the file transfer is completed, you can send a message from the server.py which you can validate in the client and break the loop as shown below.
server.py
def listen_user(user):
for x in ["f.json","g.json"]:
filename = x
print(filename)
with open(filename, 'rb') as file:
sendfile = file.read()
user.sendall(sendfile)
print('file sent' + str(x))
user.send(b"Done")
Client.py
def start_client(client):
savefilename = str(random.randint(1,10)) + 'new.json'
print(savefilename)
with client,open(savefilename,'wb') as file:
while True:
recvfile = client.recv(4096)
if recvfile.decode("utf-8") =="Done":
print('1 client')
file.close()
break
file.write(recvfile)
print('2 client')
client.close()
The call client.recv(4096) means that you are waiting for 4096 bytes to be received, then doing something with those bytes. What's likely happening in this case is that you're writing out all of the bytes, minus those that don't quite fill up the buffer at the end. This leaves the client waiting with a buffer with space that is doesn't think it is ready to write out yet.
I'm guessing that you're assuming that client.recv() will return an empty string once you've gotten all the data; this is not the case based on your code. If you want the client to be able to terminate the connection, you're going to need to send some kind of control sequence or try to otherwise assess the bytes received from the server to determined when it's time to close the connection. If you do this, you will probably want to set bufsize when calling client.recv() to 1, and instead use some other method to buffer before you write to a file.
For instance, since you're sending JSON data, you could concatenate the bytes to a variable and then repeatedly try to parse JSON. Once you have managed to successfully parse JSON, you can terminate the connection on the client side (though this would mean you have to open a new connection per file you're sending).
However, that raises the question: why do you need to close from the client side? Usually the server will just close the connection once it is done sending all of the relevant data.
I provided a WORKING client and server file.
The client sends a picture to the server.
When you comment out:
data = sock.recv(1024)
print("received: ",str(data,"UTF-8"))
the picture will not be uploaded to the server anymore...
(After receiving the upload message from the server I would like to upload another picture in the future.)
So why is calling sock.recv() after sock.sendall() messing up the communication ? ( and how should I solve it )
Client.py :
import socket
PICLOC = "/home/wr/Documents/Data/cola_big_1.jpg"
HOST = 'localhost'
PORT = 9995
# Create a socket (SOCK_STREAM means a TCP socket)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Connect to server and send data
sock.connect((HOST, PORT))
# Send a command to the server
command = "pictureRequest"
data = sock.send(bytes(command, "utf-8"))
pictures = []
pictures.append(PICLOC)
data = sock.recv(1024)
print("received : ",data.decode())
for picture in pictures:
# sending a picture to the server
f = open(picture,'rb').read()
numBytes = len(f)
x = str(numBytes)
print("numBytesToSend: ",x)
data = sock.sendall(f)
'''
data = sock.recv(1024)
print("received: ",str(data,"UTF-8"))
'''
finally:
sock.close()
Server.py
import socketserver
HOST = "localhost"
PORT = 9995
TARGETPICLOC = "/home/wr/Documents/Data/Received/cola_big_1.jpg"
class MyTCPHandler(socketserver.BaseRequestHandler):
def findProduct(self):
"""
Method called to find the product
"""
# Receiving command from the client
msg = "ok to send"
data = self.request.sendall(bytes(msg,"utf-8"))
print("send msg")
# TODO 6 pictures in array !
# Sending a picture from client to server
pictures = []
pictures.append(TARGETPICLOC)
for picture in pictures:
total_data=[]
# open the target picture-file
newFile = open(picture,'wb')
data = self.request.recv(1024)
newFile.write(data)
total_data.append(data)
while len(data)>0 :
data = self.request.recv(1024)
newFile.write(data)
total_data.append(data)
data = b''.join(total_data)
print("#bytes : ",len(data))
newFile.close()
msg = "picture uploaded"
data = self.request.sendall(bytes(msg,"utf-8"))
print("msg send ")
def handle(self):
# Receiving command from the client
data = self.request.recv(1024)
command = str(data,"utf-8")
print("command: ",command)
if command=="pictureRequest" :
self.findProduct()
print("Request ended !!")
if __name__ == "__main__":
HOST, PORT = HOST,PORT
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
Thank you for looking at this problem
So why is calling sock.recv() after sock.sendall() messing up the
communication ?
That's simply because the client by this sock.recv() call waits for data from the server (you intend to receive the picture uploaded message from the server), but the server is stuck in the loop
while len(data)>0 :
data = self.request.recv(1024)
since recv() still waits for data from the client and blocks. If the sock.recv() call is omitted, the client gets to sock.close(); only thereafter self.request.recv(1024) returns zero length data, so that the server can sense the end of the transmission and escape the while loop.
( and how should I solve it )
You could send the number of bytes to send (x = str(numBytes)) to the server prior to sending the picture, so that the server then could loop while the length of total_data is less than this number.
I have a program that launches a TCP client as well as a server, and I can send messages and files from client to the server (they are all transferred in this direction). The server is expected to be always listening, and respond each upcoming message. But I found after I sent several messages, the server never responds again, unless I relaunch connect button on GUI.
here we have in the server,
# establish connection
def conn(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.bind((self.ip, self.port))
self.s.listen(1)
print 'server ready.'
self.conn, self.addr = self.s.accept()
print 'Connected by', str(self.addr), '\n'
def recv(self):
flag = self.conn.recv(BUFFER_SIZE)
data = self.conn.recv(BUFFER_SIZE)
# this is a message
if flag=='1':
msg = "other >> %s" % data
self.conn.send("success")
print msg
return
# there will be a file
elif flag=='0':
filename = data
with open('new_'+filename, 'wb+') as f:
while True:
data = self.s.recv(BUFFER_SIZE)
if not data: break # transfer finished
f.write(data)
size = os.path.getsize(filename)
self.conn.send(str(size)) # echo size
self.conn.send("success")
return
# do not close connection unless exception raised
def run(self):
self.conn()
while True:
try:
# shoud I connect again each time here?
self.recv()
except:
self.close()
break
and in the client I have,
# expected to establish a connection
def conn(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'client ready.'
try:
self.s.connect((self.ip, self.port))
print 'connection established.'
except:
# close socket
self.s.close()
raise
def send(self, msg='', flag=1):
if flag:
self.s.send(str(flag))
self.s.send(msg)
sent = self.s.recv(BUFFER_SIZE)
print sent
else:
self.s.send(str(flag))
self.s.send(msg) # send filename
# send file in buffer-size
with open(msg, 'rb') as f:
while 1:
data = f.read(BUFFER_SIZE)
if not data: break
self.s.send(data) # send block
sent = self.s.recv(BUFFER_SIZE)
print 'sent: %s bytes' % sent
The problem is, should I put client.socket.connect() in each send function or I just leave it established and trust it would not down? And in the server, should I close connection after each message received? And why my connection is mysteriously down after a short time?
Another question is I noticed some code examples transfer files from server to client using conn.send(), instead, I sent files from client to server by socket.send(). Will this cause a problem?
I think there is something wrong with function name which may cause your problem.
Change function name in your server code:
...
def connection(self):
...
...
def run(self):
self.connection()
while True:
...
Tell me if it works.
I'm trying to send file from client to server in python. It is sending without any problem but I want to save that received file with same file name. I'm not getting idea how to save that file with same file name as it is sent from Client to Server.The code I've wrote for this is :
Client Code
import socket, os, shutil
from stat import ST_SIZE
HOST=raw_input("Please enter IP-address : ")
PORT=int(raw_input("Please enter PORT Number : "))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
if s.recv(8)!='READY':
raw_input('Unable to connect \n\n Press any key to exit ...')
s.close()
exit()
path=raw_input("Please enter the complete PATH of your file : ")
f=open(path,'rb')
fsize=os.stat(f.name)[ST_SIZE]
s.sendall(str(fsize).zfill(8))
sfile = s.makefile("wb")
shutil.copyfileobj(f, sfile)
sfile.close()
s.close()
f.close()
Server Code
import socket
import shutil
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = ''
PORT = 23240
s.bind((HOST, PORT))
s.listen(3)
conn, addr = s.accept()
print 'conn at address',addr
conn.sendall('READY')
i=1
f = open(r'file_'+ str(i)+".txt",'wb')
i=i+1
print 'File size',fsize
sfile = conn.makefile("rb")
shutil.copyfileobj(sfile, f)
sfile.close()
f.write(conn.recv(fsize))
f.close()
conn.close()
s.close()
Your code is not very robust. recv(cnt) delivers up to cnt bytes of data, or less. So it's not sure, you read the whole file. It is even not sure, you get the "READY" in one recv. Instead, you have to use something like that:
def recv_all(sock, bufsize):
result = ''
while bufsize>0:
data = sock.recv(min(bufsize, 4096))
if not data:
raise IOError("Socket closed")
result += data
bufsize -= len(data)
return result
If you want to know the filename at the server, you also have to transfer it to the server, too. By the way, "READY" has 5 characters, not 8.