this is my UDP-Server very according to the UDP-Server-Example from the python-wiki:
# ----- receiver.py -----
#!/usr/bin/env python
from socket import *
import sys
import select
host="192.168.88.51"
port = 1337
s = socket(AF_INET,SOCK_DGRAM)
s.bind((host,port))
addr = (host,port)
buf=128
data,addr = s.recvfrom(buf)
print "Received File:"
f = open("out.jpg",'wb')
data, addr = s.recvfrom(buf)
try:
while(data):
f.write(data)
s.settimeout(1)
data,addr = s.recvfrom(buf)
except timeout:
f.close()
s.close()
print "File Downloaded"
This code works fine and I'm able to receive ONE file at a time. But I have multiple clients and I'd like to receive every file coming in, so every time a new connection is established (from one certain IP).
Any suggestions?
First of all, if you want an asynchronous server, it's better to not write things from scratch with sockets. Instead, use packages like asyncio or Twisted.
Coming to your problem, it's more convenient to go with a TCP-focused socket, therefore you should use SOCK_STREAM instead of the UDP type SOCK_DGRAM.
First, define a function for downloading:
def get_file(s):
s.settimeout(1)
with open("out.jpg",'wb') as f:
data, addr = s.recv(buf)
try:
while(data):
f.write(data)
data, addr = s.recv(buf)
except timeout:
print "File Downloaded"
After setting up the constants (hostname, port number and so on), do something like the following (and do from threading import Thread first!):
s = socket(AF_INET,SOCK_DGRAM)
s.bind((host,port))
while True:
print "Waiting for connection..."
data, addr = s.recvfrom(buf)
print "... connection from:", addr
Thread(target=get_file, args=(s,)).start() #starts a new thread for file download, addr acts like a filename
Related
I'm trying to run a client/server script, where the client sends a file to the server and waits for responses until the server sends a stop message.
The problem is: once the connection is established the client starts sending data but until I press CTRL-C the server cannot recreate the file. Only after CTRL-C print "file is fully created" and the file becomes visible, instead, before it's seems to be waiting for something. idk where the problem is. Also tried changing condition on send loop using len(), but doesn't work. Anyone know how to fix it ?
client.py :
import socket # Import socket module
# from threading import Thread
s = socket.socket() # Create a socket object
HOST = "101.xx.x.xxx" # public IP address
PORT = 4243 # Reserve a port for your service.
PDF_PATH = "exam.pdf"
s.connect((HOST, PORT))
def send():
f = open(PDF_PATH, "rb")
while data := f.read(4096):
s.send(data)
f.close()
return
def receive():
while 1:
exercise = s.recv(4096)
if exercise == "stop!":
s.close()
break
f = open(f"{exercise}.txt", "wb")
while data := f.read(4096):
f.write(data)
return
def main():
send()
receive()
if __name__ == "__main__":
main()
server.py :
import socket
from threading import Thread
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
HOST = socket.gethostname()
IP = socket.gethostbyname(HOST)
PORT = 4243
s.bind(('', PORT))
s.listen(5)
def receive_file(conn, i):
f = open(f"exam.pdf", "wb")
while received := conn.recv(4096):
f.write(received)
print("File is fully copied\n")
f.close()
def send_result(conn,i):
while 1:
nbr = str(input("which exercise? "))
if nbr == "stop!":
break
f = open(f"exercise{nbr}.txt", "rb")
conn.send(bytes(f"exercise{nbr}.txt", encoding="utf-8"))
while data := f.read(4096):
conn.send(data)
f.close()
def main():
try:
while 1:
i = 0
conn, addr = s.accept()
print("Got connection from", addr)
# c.send(b"Thank you for connecting")
t = Thread(target=receive_file, args=(conn, i))
t.start()
t.join()
t = Thread(target=send_result, args=(conn, i))
t.start()
t.join()
except KeyboardInterrupt:
print("interrupting \n")
conn.close()
s.close()
if _name_ == '_main_':
main()
conn.recv() in the server won't return '' (no more data) unless the client closes the connection or calls shutdown(SHUT_WR) to indicate sends are complete:
def send():
with open(PDF_PATH, "rb") as f:
while data := f.read(4096):
s.sendall(data)
s.shutdown(socket.SHUT_WR)
An alternative is to design a protocol that sends the length of data before the data so you know when you've received the complete transmission. This would be required if you need to send more than one thing without closing the socket or shutting down sends. You're going to need this to make the receive portion of the server work if you want to send more than one exercise file.
Refer to this answer for an example of sending multiple files over a socket.
I am having the above issue. The client is suppose to ask for a filename and send the file name to the server after which the server will open the file and display it. Problem is that the server isn't opening the file and displaying it.
Below is the client.
#!/usr/bin/env python3
import socket, os.path, datetime, sys
def Main():
host = '127.0.0.1'
port = 50001
s = socket.socket()
s.connect((host, port))
Filename = input("Type in ur file ")
s.send(Filename.encode('utf-8'))
data = s.recv(1024).decode('utf-8')
s.close()
if __name__ == '__main__':
Main()
Below is the server
#!/usr/bin/env python3
import socket
import os
import sys
def Main():
host = '127.0.0.1'
port = 50001
s = socket.socket()
s.bind((host,port))
print("server Started")
s.listen(1)
c, addr = s.accept()
print("Connection from: " + str(addr))
while True:
data = c.recv(1024).decode('utf-8')
myfile = open(data, "r")
if not data:
break
print("from connected user: " + myfile)
c.close()
if __name__ == '__main__':
Main()
I've made few minimal adjustments to your code with which it runs as so that server.py continuously listens on a given port and sends back data which each invocation of client.py asks for.
server.py
#!/usr/bin/env python3
import socket
import os
import sys
def Main():
host = '127.0.0.1'
port = 50001
s = socket.socket()
s.bind((host,port))
print("server Started")
s.listen(1)
while True:
c, addr = s.accept()
print("Connection from: " + str(addr))
filename = ''
while True:
data = c.recv(1024).decode('utf-8')
if not data:
break
filename += data
print("from connected user: " + filename)
myfile = open(filename, "rb")
c.send(myfile.read())
c.close()
if __name__ == '__main__':
Main()
client.py
#!/usr/bin/env python3
import socket, os.path, datetime, sys
def Main():
host = '127.0.0.1'
port = 50001
s = socket.socket()
s.connect((host, port))
Filename = input("Type in ur file ")
s.send(Filename.encode('utf-8'))
s.shutdown(socket.SHUT_WR)
data = s.recv(1024).decode('utf-8')
print(data)
s.close()
if __name__ == '__main__':
Main()
And now a bit of explanation.
On the server side. The outer loop accepts a connection, then reads from the connection until done (more on this later). Prints your debugging info, but note you were trying to print the file object and not the filename (which would fail trying to concatenate). I also open the file in binary mode (that way I can skip the str -> bytes translation.
On the client side. I've added closing the writing end of the socket when the file has been sent. Note you might want to use sendall instead of send for this use case: check those docs links for details. And I've added a print for the incoming data.
Now that bit with shutting down the writing end in the client and the inner loop reading (and also related to the sendall hint. Which BTW also holds true for the server side, otherwise you should loop, as you might see your content truncated; other option is to also have a sending loop.). Stream sockets will guarantee you get your bytes in in order you've send them. On itself it has no idea whether your message is complete and it also does not guarantee in how many and how large chunks will the data be sent and received (resp.).
The inner loop of server keep reading until we see an EOF (we've receive zero length string in python socket). This would happen (be returned by recv when the remote socket (or at least its writing end) has been shut down. Since we still want to reuse the connection, we only do that on the sending end in the client. Hope this helps you to move ahead.
Greetings and apologies in advance if it looks a real novice question. I am new to python, or programming for that matter. I am writing a code that sends data from client to server. The data I need to send is from an csv file, which has around 10,000 rows. Currently I am sending the data in a large buffer as a whole, but I would prefer to send it row by row and also receive it the same way. I am not sure if I should use the split() function or there are any better ways to do the same thing.
The client...
import socket
HOST = 'server IP'
PORT = 42050
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
f = open('csvfile.csv', 'rb')
l = f.read(409600)
while True:
print l
s.send(l)
break
f.close()
print "Done Sending"
s.close()
The server...
import socket
HOST = 'local IP'
PORT = 42050
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
print "Server running", HOST, PORT
s.listen(5)
conn, addr = s.accept()
print'Connected by', addr
while True:
data = conn.recv(409600)
print repr(data)
if not data: break
print "Done Receiving"
conn.close()
Thanks in advance for the help.
im not sure what your question actually is ... but its pretty easy to send and receive lines
#client.py
for line in open("my.csv"):
s.send(line)
#server.py
def read_line(sock):
return "".join(iter(lambda:sock.recv(1),"\n"))
iter(lambda:sock.recv(1),"\n")
is essentially the same as
result = ""
while not result.endswith("\n"): result += sock.recv(1)
Hello stackoverflow users, so I have this problem where i am trying to code a web server but the script ends before I can even test if it works. So my question is how can I make the script so that it will keep running forever?
#import threading
#import socket
#import signal # Signal support (server shutdown on signal receive)
import multiprocessing
#import queue
def MasterProcessA():
import socket
import multiprocessing
import threading
HOST = '97.107.139.231' # Symbolic name, meaning all available interfaces
PORT = 8080 # Arbitrary non-privileged port
#print(PORT)
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#print 'Socket created'
#Bind socket to local host and port
#try:
socket.bind((HOST, PORT))
#except socket.error as msg:
##print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
#print 'Socket bind complete'
#Start listening on socket
socket.listen(100)
print "starting server"
def ConnProcessA():
print "thread step one"
Conn, Address = socket.accept()
t = threading.Thread(target=ConnectionProcessorA)
print "thread step two"
#t.daemon = True
t.start()
#print("A Got connection from:", Address)
DataRecived = Conn.recv(1024) #receive data from client
DataRecived = bytes.decode(DataRecived) #decode it to string
print DataRecived
Conn.send("HELLO World")
Conn.clouse()
ConnProcessA = threading.Thread(target=ConnProcessA)
#t.daemon = True
ConnProcessA.start()
MasterProcessA = multiprocessing.Process(target=MasterProcessA)
MasterProcessA.start()
There are several issues with your codes.
The thread doesn't run. You need to modify:
ConnProcessA.start()
ConnProcessA.join()
ConnectionProcessorA is not included in the codes you pasted. So I have to comment out these 2 lines:
t = threading.Thread(target=ConnectionProcessorA)
t.start()
Name shadowing. Refer to these lines:
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ConnProcessA = threading.Thread(target=ConnProcessA)
MasterProcessA = multiprocessing.Process(target=MasterProcessA)
You named instances with existing module/function names. Name shadowing is very dangerous. Just try to execute any of the 3 lines twice, you will see the error.
On the other side, it's ok to reuse a variable to hold different things, if straightforward enough. E.g., following two lines are close enough to avoid confusion:
DataRecived = Conn.recv(1024) #receive data from client
DataRecived = bytes.decode(DataRecived) #decode it to string
Seems your socket server is to continuously listen to a same port, then you probably need to add s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1). As said at the most bottom of the doc.
A less severe point, in Python coding convention, CapWords is usually used for class names ref. You used it for both function names and variable names. Better to keep your codes consistent.
I am implementing a program with a server and multiple clients. All clients send data to the server and a server check out the step of each client. If all client's steps are the same, a server sends new data to all clients to do next step. And it continues this procedure again and again.
However, when I run my program, it cannot communicate each other. Here are my code. Would you give me some hints?
client & server
#client
from socket import *
from sys import *
import time
import stat, os
import glob
# set the socket parameters
host = "localhost"
port = 21567
buf = 1024
data = ''
addr = (host, port)
UDPSock = socket(AF_INET, SOCK_DGRAM)
UDPSock.settimeout(100)
def_msg = "=== TEST ==="
#FILE = open("test.jpg", "w+")
FILE = open("data.txt","w+")
while (1):
#data, addr = UDPSock.recvfrom(buf)
print "Sending"
UDPSock.sendto(def_msg, addr)
#time.sleep(3)
data, addr = UDPSock.recvfrom(buf)
if data == 'done':
FILE.close()
break
FILE.write(data)
print "Receiving"
#time.sleep(3)
UDPSock.close()
# server program for nvt
from socket import *
import os, sys, time, glob
#import pygame
import stat
host = 'localhost'
port = 21567
buf = 1024
addr = (host, port)
print 'test server'
UDPSock = socket(AF_INET, SOCK_DGRAM)
UDPSock.bind(addr)
msg = "send txt file to all clients"
#FILE = open("cam.jpg", "r+")
FILE = open("dna.dat","r+")
sending_data = FILE.read()
FILE.close()
tmp_data = sending_data
while (1):
#UDPSock.listen(1)
#UDPSock.sendto(msg, addr)
#FILE = open("gen1000.dat","r+")
#sending_data = FILE.read()
#FILE.close()
#print 'client is at', addr
data, addr = UDPSock.recvfrom(buf)
#time.sleep(3)
print data
#msg = 'hello'
#
tmp, sending_data = sending_data[:buf-6], sending_data[buf-6:]
if len(tmp) < 1:
msg = 'done'
UDPSock.sendto(msg, addr)
print "finished"
sending_data = tmp_data
UDPSock.sendto(tmp, addr)
print "sending"
#time.sleep(3)
UDPSock.close()
A server must perform the sequence socket(), bind(), listen(), accept() (possibly repeating the accept() to service more than one client), while a client only needs the sequence socket(), connect().
Your missing listen() i saw first. Listen for connections made to the socket.
More on this here: link text
Look at this: http://heather.cs.ucdavis.edu/~matloff/Python/PyNet.pdf
It's a very good Python networking tutorial including working examples of a client and server. Now, I'm not an expert on this, but it looks to me like your code is overcomplicated. And what's the deal with all the commented-out lines?
Quote from question:
#UDPSock.listen(1)
#UDPSock.sendto(msg, addr)
#FILE = open("gen1000.dat","r+")
#sending_data = FILE.read()
#FILE.close()
End quote
Those look like some pretty important lines to me.
Also, make sure the computers are connected. From a prompt run:
ping [IP]
where [IP] is the IP address of the other machine(Note: if you're not connected to the same LAN, this becomes much harder as you might then need port forwarding and possibly static IPs).