I have a vpn (using OpenVPN) with mulitple clients connected to a server (at DigitalOcean). The connection is very good and I am able access every client placed behind their respective firewalls when they are connected to their respective routers through ssh. I want to use python scripts to automatically send files from multiple clients to server and vice versa. Here's the code I am using so far:
Server:
#!/usr/bin/env python
import socket
from threading import Thread
from SocketServer import ThreadingMixIn
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print "[+] New thread started for "+ip+":"+str(port)
def run(self):
while True:
data = conn.recv(2048)
if not data: break
print "received data:", data
conn.send(data) # echo
TCP_IP = '0.0.0.0'
TCP_PORT = 62
BUFFER_SIZE = 1024 # Normally 1024
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpsock.listen(4)
print "Waiting for incoming connections..."
(conn, (ip,port)) = tcpsock.accept()
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
for t in threads:
t.join()
Client:
#!/usr/bin/env python
import socket
TCP_IP = '10.8.0.1'
TCP_PORT = 62
BUFFER_SIZE = 1024
MESSAGE = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
print "received data:", data
The problem is im not able to get a connection. The server only prints "Waiting for incoming connections..." and the client does not seem to find its way to the server. Is there anyone who can take a look at this and give me some feedback on wath I am doing wrong?
Can you try something like this?
import socket
from threading import Thread
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print "[+] New thread started for "+ip+":"+str(port)
def run(self):
while True:
data = conn.recv(2048)
if not data: break
print "received data:", data
conn.send(b"<Server> Got your data. Send some more\n")
TCP_IP = '0.0.0.0'
TCP_PORT = 62
BUFFER_SIZE = 1024 # Normally 1024
threads = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(("0.0.0.0", 5000))
server_socket.listen(10)
read_sockets, write_sockets, error_sockets = select.select([server_socket], [], [])
while True:
print "Waiting for incoming connections..."
for sock in read_sockets:
(conn, (ip,port)) = server_socket.accept()
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
for t in threads:
t.join()
Now the client will have something like below:
import socket, select, sys
TCP_IP = '0.0.0.0'
TCP_PORT = 62
BUFFER_SIZE = 1024
MESSAGE = "Hello, Server. Are you ready?\n"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, 5000))
s.send(MESSAGE)
socket_list = [sys.stdin, s]
while 1:
read_sockets, write_sockets, error_sockets = select.select(socket_list, [], [])
for sock in read_sockets:
# incoming message from remote server
if sock == s:
data = sock.recv(4096)
if not data:
print('\nDisconnected from server')
sys.exit()
else:
sys.stdout.write("\n")
message = data.decode()
sys.stdout.write(message)
sys.stdout.write('<Me> ')
sys.stdout.flush()
else:
msg = sys.stdin.readline()
s.send(bytes(msg))
sys.stdout.write('<Me> ')
sys.stdout.flush()
The output is as below:
For server -
Waiting for incoming connections...
[+] New thread started for 127.0.0.1:52661
received data: Hello, World!
Waiting for incoming connections...
received data: Hi!
received data: How are you?
For client -
<Server> Got your data. Send some more
<Me> Hi!
<Me>
<Server> Got your data. Send some more
<Me> How are you?
<Me>
<Server> Got your data. Send me more
<Me>
In case you want to have an open connection between the client and server, just keep the client open in an infinite while loop and you can have some message handling at the server end as well. If you need that I can edit the answer accordingly. Hope this helps.
Related
I want to implement multithreaded-server receives connection from multiple clients on different VMs. 3 VMs are in the same subnet. I would ask how to make it can connect to each other by configuring the network on vms and how to change ip and port in code. Here is the code on server:
import socket
from threading import Thread
from SocketServer import ThreadingMixIn
TCP_IP = 'localhost'
TCP_PORT = 12345
BUFFER_SIZE = 1024
class ClientThread(Thread):
def __init__(self,ip,port,sock):
Thread.__init__(self)
self.ip = ip
self.port = port
self.sock = sock
print " New thread started for "+ip+":"+str(port)
def run(self):
filename='mytext.txt'
f = open(filename,'rb')
while True:
l = f.read(BUFFER_SIZE)
while (l):
self.sock.send(l)
l = f.read(BUFFER_SIZE)
if not l:
f.close()
self.sock.close()
break
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpsock.listen(5)
print "Waiting for incoming connections..."
(conn, (ip,port)) = tcpsock.accept()
print 'Got connection from ', (ip,port)
newthread = ClientThread(ip,port,conn)
newthread.start()
threads.append(newthread)
for t in threads:
t.join()
Client1:
import socket
TCP_IP = 'localhost'
TCP_PORT = 12345
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
with open('received_file', 'wb') as f:
print 'file opened'
while True:
data = s.recv(BUFFER_SIZE)
print('data=%s', (data))
if not data:
f.close()
print 'file close()'
break
f.write(data)
s.close()
print('connection closed')
Client2:
import socket
TCP_IP = 'localhost'
TCP_PORT = 12345
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
with open('received_file', 'wb') as f:
print 'file opened'
while True:
data = s.recv(BUFFER_SIZE)
print('data=%s', (data))
if not data:
f.close()
print 'file close()'
break
f.write(data)
s.close()
print('connection closed')
When you are binding to "localhost" IP address it means that your server starts listening on "loopback" internal virtual networking interface with address 127.0.0.1 which can be accessed from local machine but not from outside.
Your server does not listen on any physical interfaces which look into world so even properly configured clients would not be able to connect to your server from remote nodes.
You can replace "localhost" with "0.0.0.0" - which means "bind to all available interfaces".
This means that you can start your server without knowledge of IP address(es) of your own server.
It will be waiting incoming connections on all physical and virtual interfaces which are configured in your VM.
TCP_IP = '0.0.0.0'
tcpsock.bind((TCP_IP, TCP_PORT))
But clients need to know IP address of your server to be able to connect to it.
Right now your clients try to connect to theirs own VM by using IP address 127.0.0.1
You need to provide clients with real IP address of your server for them to connect to it.
Lets assume that your server has address 192.168.4.4
Then your client code should look this way:
TCP_IP = '192.168.4.4'
s.connect((TCP_IP, TCP_PORT))
From client I am trying to send a txt file to server.
client.py
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 8340
BUFFER_SIZE = 1024
server_addr = (TCP_IP, TCP_PORT)
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect(server_addr)
file = open(r"C:\Users\sakthi\Desktop\Hi.txt",'r')
transfer = file.read(BUFFER_SIZE)
while transfer:
c.send(transfer.encode())
transfer = file.read(1024)
print (s.recv(BUFFER_SIZE).decode())
c.close()
Server.py
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 8340
BUFFER_SIZE = 1024 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
final = open(r"C:\Users\sakthi\Desktop\final.txt", 'a+')
while 1:
print('Connection address:', addr)
r = conn.recv(BUFFER_SIZE).decode()
if not r:break
final.write(r)
print("received data:", r)
k="file received"
conn.send(k.encode())
conn.close()
Once the file is received, server will send message "file received" to client.
Client will print the message "file received" and close the connection
When I run the code, server.py is not coming out of while loop
while 1:
print('Connection address:', addr)
r = conn.recv(BUFFER_SIZE).decode()
if not r:break
final.write(r)
print("received data:", r)
r = conn.recv(BUFFER_SIZE).decode() keeps listening for new messages, but the client has transferred all messages.
size of the file is 1.14 KB.
Can anybody tell me what's wrong in my program?
I found the solution
Note our statement that recv() blocks until either there is data available to be read or the sender has closed the connection holds only if the socket is in blocking mode. That mode is the default, but we can change a socket to nonblocking mode by calling setblocking() with argument 0.
I have modified the server.py
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 8340
BUFFER_SIZE = 1024 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
conn.setblocking(0)
final = open(r"C:\Users\sakthi\Desktop\final.txt", 'a+')
while 1:
try:
print('Connection address:', addr)
r = conn.recv(BUFFER_SIZE).decode()
final.write(r)
print("received data:", r)
except:
break
k="file received"
conn.send(k.encode())
conn.close()
Now I am able to receive the file and send message "file received" to client and connection is closed.
non-blocking socket,error is always
http://www.mws.cz/files/PyNet.pdf
I have this simple code:
import socket
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((host, port))
socket.listen()
while True:
client_socket, addr = socket.accept()
send = input("Send: ") # but I need a way to send it to all the clients connected
if send == "devices":
# here I'd have a list of all devices connected
client_socket.send(send.encode())
data = client_socket.recv(4096)
print (data)
As I wrote in the comments, I need a way to manage them all in one. How can I do? Maybe with _thread library?
You could mainitain a list of clients that can be passed to an external function that performs an action on all clients.
import socket
host = ''
port = 1000
max_connections = 5
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((host, port))
socket.listen(max_connections)
clients = [] # Maintain a list of clients
try:
while True:
client_socket, addr = socket.accept()
clients.append(client_socket) #Add client to list on connection
i_manage_clients(clients) #Call external function whenever necessary
except KeyboardInterrupt:
socket.close()
def i_manage_clients(clients): #Function to manage clients
for client in clients:
client.send('Message to pass')
The above example demonstrates how send data to all clients at once. You could use the
import socket
from thread import *
host = ''
port = 1000
max_connections = 5
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((host, port))
socket.listen(max_connections)
try:
while True:
client_socket, addr = socket.accept()
start_new_thread(i_manage_client, (client_socket,addr))
except KeyboardInterrupt:
socket.close()
def i_manage_client(client_socket, addr): #Function to manage clients
client_socket.send('Message to pass')
data = client_socket.recv(4096)
print(client_socket)
print(addr)
print(data)
I am a total beginner in Python and today I tried to create a simple chat-program. So far it doesn't work too bad, but I am unable to communicate between the server and the client. I can only send from the server to the client but not in the other direction. I tried it with multithreading and these are the results:
Server:
import socket
import threading
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "127.0.0.1"
port = 4444
s.bind((host, port))
s.listen(3)
conn, addr = s.accept()
print("Connection from: "+str(addr[0])+":"+str(addr[1]))
def recv_data():
while True:
data = s.recv(2048).decode('utf-8')
print(data)
def send_data():
while True:
msg = input(str(socket.gethostname())+"> ")
msg = str(host + "> ").encode('utf-8') + msg.encode('utf-8')
conn.send(msg)
#t1 = threading.Thread(target=recv_data)
t2 = threading.Thread(target=send_data)
#t1.start()
t2.start()
Client:
import socket
import threading
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "127.0.0.1"
port = 4444
s.connect((host, port))
print("Connected to: "+ host)
def recv_data():
while True:
data = s.recv(2048)
data = data.decode('utf-8')
print(data)
def send_data():
while True:
msg = input(str(host)+"> ").encode('utf-8')
s.send(msg)
t1 = threading.Thread(target=recv_data)
#t2 = threading.Thread(target=send_data)
t1.start()
#t2.start()
This code works; the server can send, the client receive, but whenever I uncomment the second thread, so that it can do both I get an error:
OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
I can't seem to find a solution, so please help, what am I doing wrong? :D
conn, addr = s.accept()
def recv_data():
while True:
data = s.recv(2048).decode('utf-8')
print(data)
conn is actually the socket you want to send or recv. The error occurs because you are trying to recv from the server socket, which is illegal action. Therefore you need to change s to conn if you want to make it work.
I'm writing a very basic chat room in python. Clients connect and any message from a client is relayed to all clients. The problem I'm having is getting the client to listen and send messages at the same time. It seems to only do either one. I've set up a separate listening client and confirmed that the message is received but the listening server cannot send anything.
Currently the client has to send data before getting a response from the server, but I want clients to be able to receive data before sending - otherwise the chat room won't work. I attempted using clientsock.settimeout() and then use recv but it did not solve the issue as it did not move past the input part.
server.py
#!/usr/bin/python
#socket server using threads
import socket, sys, threading
from _thread import *
HOST = 'localhost'
PORT = 2222
lock = threading.Lock()
all_clients = []
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print ("Socket created")
#bind socket to local host and port
try:
s.bind((HOST, PORT))
except socket.error as msg:
print ("Bind failed. Error code: " + str(msg[0]) + ' Message ' + msg[1])
sys.exit(0)
print ("Socket bind complete")
#Start listening on socket
s.listen(5)
print ("Socket now listening")
#function for handling connections. This will be used to create threads
def clientthread(conn):
#sending message to connected client
conn.send("Welcome to the server. Type something and hit enter\n".encode('utf-8'))
#infinite loop so that function does not terminate and thread does not end
while True:
#receiving data from client
data = conn.recv(1024)
reply = "OK..." + str(data, "utf-8")
if not data:
break
with lock:
for c in all_clients:
c.sendall(reply.encode('utf-8'))
#came out of loop
conn.close()
#keep talking with the client
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
with lock:
all_clients.append(conn)
print ("Connected with " + addr[0] + ":" + str(addr[1]))
#start new thread takes 1st argument as a function name to be run, second
#is the tuple of arguments to the function
start_new_thread(clientthread ,(conn,))
s.close()
client.py
#!/usr/bin/python
import socket, sys
#client to transfer data
def main():
#create tcp stocket
clientsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#connect the socket to the server open port
server_address = ('localhost', 2222)
print ("connecting to %s port %s" % server_address)
clientsock.connect(server_address)
#receive data
data = clientsock.recv(1024)
print(str(data, "utf-8"))
while 1:
#send data
message = "sean: " + input()
clientsock.send(message.encode('utf-8'))
#look for the response
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = clientsock.recv(1024)
amount_received += len(data)
print ("received %s " % data)
print ("closing socket")
clientsock.close()
main()
new_client.py
#!/usr/bin/python
import socket, sys
from threading import Thread
#client for chat room
def send_msg(sock):
while True:
data = input()
sock.send(data.encode('utf-8'))
def recv_msg(sock):
while True:
stuff = sock.recv(1024)
sock.send(stuff)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 2222)
sock.connect(server_address)
print("Connected to chat")
Thread(target=send_msg, args=(sock,)).start()
Thread(target=recv_msg, args=(sock,)).start()
Create two threads, one for receiving the other for sending. This is the simplest way to do.
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect("address")
def send_msg(sock):
while True:
data = sys.stdin.readline()
sock.send(data)
def recv_msg(sock):
while True:
data, addr = sock.recv(1024)
sys.stdout.write(data)
Thread(target=send_msg, args=(sock,)).start()
Thread(target=recv_msg, args=(sock,)).start()