This question already has answers here:
Server and client on two different networks with python?
(1 answer)
Java socket client to server on different network.
(2 answers)
Connecting 2 devices on different networks using Python Sockets
(1 answer)
Closed 4 months ago.
I need someone to explain what is happening here. I have two code files; a server.py and a client.py. I basically created an area where I can send messages from clients to other connected clients to that server. It works when I run different instances on my own computer, but when I sent it to my partner to test it out with me (he is about an hour drive away from me; different WiFi networks), when he ran it while I had the server running, he received a timeout error.
What is going on here, where I can connect to it from my own device and someone else can't?
Here is my code, followed by the error screenshot my partner received:
server.py
import socket
import threading
serverSocket = socket.socket()
print("Server created")
ip = socket.gethostname()
port = 5737
serverSocket.bind((ip, port))
print(f"Server bound with ip {ip} port {port}")
serverSocket.listen()
clients = []
def broadcast(data, clientc): #new...
for client in clients:
if client == clientc:
pass
else:
print("Sending ", data.decode(), "to ", client)
client.send(data)
def threaded_client(clientConnection):
clientConnection.send(str.encode(f"Hello, {clientAddress}")) #on connection, thread start
while True: #while thread running
try:
data = clientConnection.recv(2048) #receiving info
if not data: #received empty info
print("Disconnected")
break
else: #received actual data
print("Received ", data.decode(), "from ", clientAddress)
broadcast(data, clientConnection) #new
except:
break
print("Lost connection from ", clientAddress)
clientConnection.close() #thread end, on disconnection
while(True): #accepts client connection
(clientConnection, clientAddress) = serverSocket.accept()
print("Connected to ", clientAddress)
clients.append(clientConnection) #new
thread = threading.Thread(target=threaded_client, args=(clientConnection,)) #new
thread.start() #new
client.py
import socket
import threading
socketObject = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socketObject.connect((socket.gethostname(), 5737))
print("Connected to server")
def client_receive():
while(True):
try:
data = socketObject.recv(2048)
print(data.decode())
except:
print("Error... Disconnecting...")
socketObject.close()
break
def client_send():
while(True):
data = input("")
socketObject.send(data.encode())
receive_thread = threading.Thread(target=client_receive)
receive_thread.start()
send_thread = threading.Thread(target=client_send)
send_thread.start()
Screenshot of error: screenshot
Related
So I am writing this program that will allow me to run commands from a different computer on the same network (my own version of ssh) in Python. I want the client program to run in the background of the target which I've already figured out the logistics to. What I would like to do is start the client program and never have to start it again but after I close the server program on the host computer, I get tons of errors. What I would like to do is after I close the host program, the client will continue to try to connect to the server program until I run it again. The code for my client program is here:
import socket
import os
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def connect():
try:
s.connect(('localhost', 1234))
except:
connect()
while True:
connect()
while True:
try:
msg = s.recv(1024)
os.system(msg.decode("utf-8"))
except:
s.connect('localhost', 1234)
The code for my host program is here:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 1234))
s.listen(5)
def main():
while True:
clientsocket, address = s.accept()
while address != None:
message = input("Enter Message: ")
messageb = message.encode("utf-8")
clientsocket.send(messageb)
main()
Note: I will change the address from localhost when I put this on a different computer.
Never do the following to start over a function without understanding the consequences of recursion. A function calling itself is called recursion and uses stack space. This will crash if the stack hits the recursion limit.
def connect():
try:
s.connect(('localhost', 1234))
except:
connect()
Here's a solution.
client.py:
import socket
import time
while True:
s = socket.socket()
try:
print('Trying to connect...')
s.connect(('localhost',8000))
print('Connected.')
try:
while True:
data = s.recv(1024)
if not data: break # server closed connection if nothing received.
print(data)
finally:
s.close()
print('Disconnected.')
except ConnectionError: # Any type of connection error, e.g. refused, aborted, reset.
time.sleep(1)
server.py:
import socket
import time
s = socket.socket()
s.bind(('',8000))
s.listen()
while True:
c,a = s.accept()
print(f'Connected: {a}')
try:
while True:
c.send(b'message')
time.sleep(1)
except ConnectionError:
c.close()
print(f'Disconnected: {a}')
Note also that TCP is a streaming protocol. It has no concept of messages. Take the time.sleep(1) out and the messages will all run together. A proper implementation will have a protocol to extract complete messages from the byte stream such as fixed sized messages, size transmitted followed by message, delimiter bytes like newlines between messages, etc.
I'm quite new to socket programming, and I was wondering why the client stops responding after I send 3 messages to the server. Basically I send a message twice and the server responds to the client. The third time, the client just runs infinitely and the server doesn't receive anything.
Does it have something to do with overload? How does that work, especially with socket.listen()
Here is the code for reference:
client.py
# Import socket module
import socket
# Create a socket object
s = socket.socket()
# Define the port on which you want to connect
port = 12345
# connect to the server on local computer
s.connect(('127.0.0.1', port))
while True:
msg = input("Enter your message: ")
if msg != "quit":
s.send((msg).encode())
else:
# close the connection
s.close()
# receive data from the server
new_msg = (s.recv(1024).decode())
print ("[CLIENT]: ", new_msg)
server.py
# first of all import the socket library
import socket
# next create a socket object
s = socket.socket()
print ("Socket successfully created")
# reserve a port on your computer in our
# case it is 12345 but it can be anything
port = 12345
# Next bind to the port
# we have not typed any ip in the ip field
# instead we have inputted an empty string
# this makes the server listen to requests
# coming from other computers on the network
s.bind(('', port))
print ("socket binded to %s" %(port))
# a forever loop until we interrupt it or
# an error occurs
while True:
# put the socket into listening mode
s.listen(20)
print ("socket is listening")
# Establish connection with client.
c, addr = s.accept()
print('Got connection from', addr)
msg = c.recv(1024).decode()
if msg == "quit":
# Close the connection with the client
c.close()
else:
print ("[SERVER]: Recieved data: ", msg)
print ("[SERVER]: sending", msg)
c.send((msg).encode())
You still need a better understanding on how a listening socket works:
it listens only once
it accepts only once per connection
it can read and send as many packets as required until either side closes the connection
at that point (and for a single threaded server) it is ready to accept a new connection
You server.py should become:
...
s.bind(('', port))
print ("socket binded to %s" %(port))
# put the socket into listening mode
s.listen(20)
print ("socket is listening")
# a forever loop until we interrupt it or
# an error occurs
while True:
# Establish connection with client.
c, addr = s.accept()
print('Got connection from', addr)
while True:
msg = c.recv(1024).decode()
if len(msg) == 0: # the client does not send anything but just closes its side
# Close the connection with the client
c.close()
print('Client disconnected')
break
else:
print ("[SERVER]: Recieved data: ", msg)
print ("[SERVER]: sending", msg)
c.send((msg).encode())
A small fix for the client side:
...
if msg != "quit":
s.send((msg).encode())
else:
# close the connection
s.close()
break # break out of the loop after closing connection
But that is not all: TCP is a stream protocol. You should be prepared for packets send from one side to be splitted or re-assembled before reaching other side. The only guarantee is that bytes arrive in same order that they were send, but not necessarily in same packets.
I'm trying to send console commands from one machine to another using Python sockets. I want the server to send back the results of the command to the client. If the client types "ls" I want the server to send back the results of running that command. Instead of the expected result, the server just says "action completed: ls". How can I fix this so the server will run the expect commands and return the result?
Server:
import socket
from subprocess import call
def main():
host = '127.0.0.1'
port = 5000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
c, addr = s.accept()
print('Connection established: ' + str(addr))
while True:
try:
data = c.recv(1024).decode('utf-8')
print('sending data: ' + data)
c.send(data.encode('utf-8'))
if data == 'q':
break
except NameError:
error = 'Command does not exist'
c.send(error.encode('utf-8'))
continue
except SyntaxError:
error = 'Command does not exist'
c.send(error.encode('utf-8'))
continue
c.close()
Client:
import socket
from subprocess import call
def main():
host = '127.0.0.1'
port = 5000
s = socket.socket()
s.connect((host, port))
message = str(input('> '))
while message != 'q':
try:
s.send(message.encode('utf-8'))
data = s.recv(1024).decode('utf-8')
print('Action completed: %s' % data)
message = str(input('> '))
except NameError:
print("Command not recognized.")
continue
except SyntaxError:
print("Command not recognized")
continue
I recently built a socket connection in order to communicate with an android device.
I decided to use UDP instead of TCP (which is what you did). For UDP as well as TCP you need a sender and a receiver on both sides of the communication.
The port number that is received in the "addr" variable changes with every connection, so you cannot use it.
What I did, I assigned two different ports one for sending from A to B and the other port to send from B to A.
Here is my server code:
import socket # socket connection
import threading # Multithreading
import time # Timeing
# ----------------------------------------------
# Variables
# ----------------------------------------------
UDPListen2Port = 12345
UDPSend2Port = 123456
Listen2IP = '' # input your local IP here
# ----------------------------------------------
# Threading class
# ----------------------------------------------
class signalProcessingThread(threading.Thread):
def __init__(self, iP, cmdIn):
threading.Thread.__init__(self)
self.iP = iP
self.cmdIn = cmdIn
def run(self):
print("Recv--", self.iP ,"--", self.cmdIn) # Display Thread Info
cmdOut = self.EvalMessage() # Actual signal processing
byteOut = bytes(cmdOut.encode("utf-8")) # Convert Server reply to bytes
sock.sendto(byteOut,(self.iP,UDPSend2Port)) # Send Server Reply to Socket
# ----------------------------------------------
# Initialize Socket
# ----------------------------------------------
sock = socket(AF_INET, SOCK_DGRAM) # -- UDP -- connection
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # in case the port was not properly closed before
sock.bind((Listen2IP,UDPListen2Port)) # bind to the port
# ----------------------------------------------
# Listen to Socket
# ----------------------------------------------
while True:
try: # wait for a connection
data,addr = sock.recvfrom(66507) # number of bytes in the message
msg = data.decode('utf-8')
newThread = signalProcessingThread(addr[0],msg)
newThread.start()
except KeyboardInterrupt:
print('Connection failed')
sock.close()
sock.close()
The client code is quite similar, with the difference that it doesn't necessarily need to run in a thread. Hope I could help.
I am trying to build a TCP Chat Program that is multithreaded. So far I think most of the functions are setup fine. When starting the server and connecting with a client only responses sent from the server are broadcasted to all clients connected. I think I figured out why that is and it comes from the CONNECTION_LIST array I have. The server appends all clients to this list and I thought I had the same thing going for the clients but the client instance never sees this list so when sending messages they messages aren't sent anywhere. I basically need a way to copy the CONNECTION_list from the server instance over to the connected clients. I been trying figure out how to possibly do this all day and its driving me crazy.
import socket
import platform
import threading
import sys
import time
import os
'''Define Globals'''
HOST = ""
PORT = 25000
ADDR = (HOST, PORT)
CONNECTION_LIST = []
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
'''Connect Client to the Server'''
def client_connect():
server_ip = input("[+] Server's IP to connect to: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client.connect((server_ip, PORT))
print("[+] Connected to Server at address: %s" %client.getpeername()[0])
except ConnectionRefusedError:
print("[*] No Server Listening at Specified Address")
sys.exit()
communicate(client)
'''Threaded loop to continue listening for new connections'''
def server_loop():
server.bind(ADDR)
server.listen(10)
print("[*] Server started on %s" %platform.node())
while True:
client_socket, client_addr = server.accept()
CONNECTION_LIST.append(client_socket)
print("\r[+] New Connection from: %s" %client_addr[0])
'''Broadcast data to all clients except sender'''
def broadcast_data(sock, message):
for socket in CONNECTION_LIST:
if socket != server and socket != sock:
try:
socket.send(str.encode("[%s] => %s" %(os.getlogin(),message)))
except:
socket.close()
CONNECTION_LIST.remove(socket)
'''Server Host Connect Back'''
def self_connect():
sc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sc.connect(("localhost", 25000))
CONNECTION_LIST.append(sc)
communicate(sc)
def communicate(client):
dump_thread = threading.Thread(target=dump, args=(client,))
dump_thread.start()
while True:
try:
time.sleep(0.5)
data = input("> ")
broadcast_data(client, data)
except:
print("[*] Error - Program Terminating")
client.close()
sys.exit()
def dump(client):
while True:
print(client.recv(1024).decode("utf-8"))
def main():
server_thread = threading.Thread(target=server_loop)
while True:
try:
print("Select Operating Mode")
print("---------------------")
print("1. Server Mode")
print("2. Client Mode")
mode = int(input("Enter mode of operation: "))
print("\n\n")
if mode in [1,2]:
break
else:
raise ValueError
except ValueError:
print("Enter either (1) for Server or (2) for Client")
if mode == 1:
server_thread.start()
time.sleep(1)
self_connect()
elif mode == 2:
client_connect()
main()
I have two scripts, Server.py and Client.py.
I have two objectives in mind:
To be able to send data again and again to server from client.
To be able to send data from Server to client.
here is my Server.py :
import socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.1.3"
port = 8000
print (host)
print (port)
serversocket.bind((host, port))
serversocket.listen(5)
print ('server started and listening')
while 1:
(clientsocket, address) = serversocket.accept()
print ("connection found!")
data = clientsocket.recv(1024).decode()
print (data)
r='REceieve'
clientsocket.send(r.encode())
and here is my client :
#! /usr/bin/python3
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host ="192.168.1.3"
port =8000
s.connect((host,port))
def ts(str):
s.send('e'.encode())
data = ''
data = s.recv(1024).decode()
print (data)
while 2:
r = input('enter')
ts(s)
s.close ()
The function works for the first time ('e' goes to the server and I get return message back), but how do I make it happen over and over again (something like a chat application) ?
The problem starts after the first time. The messages don't go after the first time.
what am I doing wrong?
I am new with python, so please be a little elaborate, and if you can, please give the source code of the whole thing.
import socket
from threading import *
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.1.3"
port = 8000
print (host)
print (port)
serversocket.bind((host, port))
class client(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.start()
def run(self):
while 1:
print('Client sent:', self.sock.recv(1024).decode())
self.sock.send(b'Oi you sent something to me')
serversocket.listen(5)
print ('server started and listening')
while 1:
clientsocket, address = serversocket.accept()
client(clientsocket, address)
This is a very VERY simple design for how you could solve it.
First of all, you need to either accept the client (server side) before going into your while 1 loop because in every loop you accept a new client, or you do as i describe, you toss the client into a separate thread which you handle on his own from now on.
client.py
import socket
s = socket.socket()
s.connect(('127.0.0.1',12345))
while True:
str = raw_input("S: ")
s.send(str.encode());
if(str == "Bye" or str == "bye"):
break
print "N:",s.recv(1024).decode()
s.close()
server.py
import socket
s = socket.socket()
port = 12345
s.bind(('', port))
s.listen(5)
c, addr = s.accept()
print "Socket Up and running with a connection from",addr
while True:
rcvdData = c.recv(1024).decode()
print "S:",rcvdData
sendData = raw_input("N: ")
c.send(sendData.encode())
if(sendData == "Bye" or sendData == "bye"):
break
c.close()
This should be the code for a small prototype for the chatting app you wanted.
Run both of them in separate terminals but then just check for the ports.
This piece of code is incorrect.
while 1:
(clientsocket, address) = serversocket.accept()
print ("connection found!")
data = clientsocket.recv(1024).decode()
print (data)
r='REceieve'
clientsocket.send(r.encode())
The call on accept() on the serversocket blocks until there's a client connection. When you first connect to the server from the client, it accepts the connection and receives data. However, when it enters the loop again, it is waiting for another connection and thus blocks as there are no other clients that are trying to connect.
That's the reason the recv works correct only the first time. What you should do is find out how you can handle the communication with a client that has been accepted - maybe by creating a new Thread to handle communication with that client and continue accepting new clients in the loop, handling them in the same way.
Tip: If you want to work on creating your own chat application, you should look at a networking engine like Twisted. It will help you understand the whole concept better too.