I'm trying to learn python. One of the main things I'm trying to do is create a relay that will relay sockets sent from one client to another. As I'm beginning this, I've started doing some simple modifications to a basic client/server sample script. However, what occurs is that the server itself will not or for some reason cannot print out the value that it is repeating back to the client. I only get "Recieved ''" like it's an empty string. Please help me understand and fix this?
server program
import socket
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
data = ''
message = ''
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
conn.close()
print('Received', repr(data.decode()))
client program
import socket
HOST = '192.168.56.1' # The remote host
PORT = 50007 # The same port as used by the server
x = input('Message:')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(x.encode())
data = s.recv(1024)
s.close()
print('Received', repr(data.decode()))
Good job, Stack Overflow. Now I at least know where I'm not going to find help. That is in itself helpful in some way. The one question that doesn't get deleted goes unanswered for days. lol. If anybody happens to stumble across this thread having this or a similar issue before some presumptuous, self-important chutzpah who probably enjoys the sweet, sweet smell of their own believed to be flawless fart deletes it, I suggest you find a real forum.
Related
Basically, i want to take data from pc A to send it to B (not local) in python
I tried using socket, then found out that its only working in local, except if you modify router / firewall. (atleast, its what i got from google)
But i dont want to touch these things. So i would like to know, is there a way to send data to B like i want? because i cant really modify routers (if there is a way, but with another module, i still want to know)
Also, i dont care if i need to like switch my server code, and having another language or anything, i just want the client file in python, then a way to send data to another computer
my code with socket, if you know a way to send client's data to server:
# echo-client.py
import socket
inputKey = "hi"
#Data transferring via sockets
HOST = "" # The server's hostname or IP address
PORT = 65432 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(bytes(str(inputKey), encoding='utf-8'))
import socket
#Data receiving via sockets
HOST = ""
PORT = 65432
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
connexion, addr = s.accept()
with connexion:
print(f"Connected by {addr}")
while True:
data = connexion.recv(1024)
if not data:
break
#printing in logs.txt
with open("logs.txt","wb") as log:
log.write(data)
I have a question. If your socket program is already connected to a user suppose like 192.168.0.25:4545 and in the middle of communication if I run a connect((host,port)) to that ip and port it still accepts the connection.So, is it possible to make something that would connect to the server if a prior connection to that server doesn't already exist. I tried using the router assigned port cuz its unique for each connection, but its getting overly complicated if I do it that way.
Here is the Code dealing with this question
if __name__ == "__main__":
HOST, PORT = "192.168.0.25", 4545
counter_check = 1
while True:
try:
time.sleep(8)
s = Client(HOST, PORT)
s.enable_attempt_reconnect()
if counter_check == 1:
proc = multiprocessing.Process(target=s.start_code)
proc.start() #starting the thread for reverse shell
counter_check += 1
elif proc.is_alive():
proc.terminate() #forcefully close the previous thread
proc = multiprocessing.Process(target=s.start_code)
proc.start() #start a new thread
except Exception:
continue
enable_attempt_reconnect()
def enable_attempt_reconnect(self):
while True:
time.sleep(3)
try:
self.soc.connect((self.host, self.port))
break
except Exception:
continue
Esentially what I am trying to do is if the connection from the client is lost, the client is actively looking for other ways to connect to the server, if another connection comes up, its probably because the current connection one was disconnected, so the client would would proc.terminate() the inital connection and start a newer connection.
I’ve been using a PUSH/PULL pattern in an application and it works as expected except when I switch off abruptly the computer or remove the ethernet cable in the PULL-side.
The PUSH-side keeps working with other PULL-sockets, but maintains switched off socket as if still were alive.
I have modified TCP-parameters (interval, count...) without results.
Is it possible to avoid this connection even when the host computer is switched off or the ethernet cable removed?
EDIT:
This is a small test i've made
server.py
import zmq
import time
context = zmq.Context()
socket = context.socket(zmq.PUSH)
socket.setsockopt(zmq.RCVHWM, 1)
socket.setsockopt(zmq.SNDHWM, 1)
socket.setsockopt(zmq.LINGER, 0)
socket.setsockopt(zmq.IMMEDIATE, 1)
print(socket.sndtimeo)
socket.sndtimeo = 0
socket.setsockopt(zmq.TCP_KEEPALIVE,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_CNT,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_IDLE,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_INTVL,1)
socket.bind('tcp://*:5555')
count= 0
while True:
print('Sending', count)
try:
socket.send(str(count).encode('utf-8'), zmq.NOBLOCK)
count+= 1
print('Ok')
except zmq.error.Again:
print('Error')
time.sleep(0.1)
client.py
import zmq
import time
import sys
#from common import time_utils
context = zmq.Context()
socket = context.socket(zmq.PULL)
server = '127.0.0.1:5555'
try:
server = sys.argv[1]
except IndexError:
pass
socket.setsockopt(zmq.TCP_KEEPALIVE,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_CNT,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_IDLE,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_INTVL,1)
socket.setsockopt(zmq.RCVHWM, 1)
socket.connect(server)
while True:
# Wait for next request from client
message = socket.recv()
print("Received request: ", message)
Running one instance of the server and 2 clients (one in the same machine that runs the server and one in other computer). Removing the ethernet cable of the second computer results in that the server keeps sending messages to the second client for a while.
As you can see I have tested all setsockopt.
Q : Is it possible to avoid this connection even when the host Computer is switched off?
For connection-oriented transport-classes, you may .setsockopt( zmq.IMMEDIATE, 1 ) so as to avoid storing outgoing messages on the PUSH-side for a dead connection.
As an additional step, one may add another, explicit ACK/NACK signalling-flow, that may help independently and explicitly detect any such event of a dead-man not responding on the ACK/NACK-loop(s).
Try using the ZMTP ping/pong options. These should detect the connection being lost as it runs at a higher level than the TCP sockets (which can be held open after the connection is down)
ZMQ_HEARTBEAT_IVL, ZMQ_HEARTBEAT_TIMEOUT and ZMQ_HEARTBEAT_TTL
http://api.zeromq.org/4-3:zmq-setsockopt
I created a server program and a client program in which my goal is for the client to send the server TCP packets. In my case, the client is given the IP address of the server and the port to where the packet should be sent. If I run the server code the first time for a specific port, the server program will search for a response. If I run it twice or more, I get the error "address already in use". It seems as if the socket is not properly closing.
As shown in my code, I have tried sock.shutdown() and sock.close() at the end of my program to no avail. I have also tried adding connection.close() and sock.setsockopt() however, I believe I may be confusing Python 2 with Python 3 syntax. (I am using Python 3) Adding or removing these methods results in the same error. I have posted the server code below for reference.
import socket
# TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
server_address = ('10.0.2.6', 2104)
print('Starting up {} port {}'.format(*server_address))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Allows address to be reused
sock.bind(server_address)
# Listen for incoming connections, looking for one connection.
sock.listen(1) # The number of queried connections.
while True:
# Wait for a connection
print('waiting for a connection')
connection, client_address = sock.accept()
try:
print('connection from', client_address)
# Receive the data in small chunks and then send back
while True:
data = connection.recv(90)
print('received {!r}'.format(data))
if data:
print('sending data back to the client')
connection.sendall(data)
break
else:
print('no data from', client_address)
break
finally:
print("Closing current connection") # Cleans up the connection
connection.close()
sock.shutdown(socket.SOCK_STREAM, socket.AF_NET)
sock.shutdown(1)
sock.close()
I expect the program to continue to listen on the same part with multiple executions. However, running this code once gives me the error
socket.error: [Errno 98] Address already in use.
So, I have a server script that receives an image from a client script and is supposed to send an acknowledgement saying "OK". But the acknowledgement never goes through.
Server script -
import socket,sys
s = socket.socket()
print("Socket successfully created")
port =80
s.bind(('', port))
print("socket binded to %s" %(port))
s.listen(5)
print("socket is listening")
while True:
c, addr = s.accept()
print('Got connection from', addr)
file_name=s.recv(1024)
file_name=fil_ename.decode("utf-8")
with open(file_name,"wb")as f:
while True:
data=c.recv(1024)
if not data:
break
f.write(data)
c.send(bytes('Thank you ! File received.',"utf-8"))
c.close()
Client script -
import socket
s = socket.socket()
# Define the port on which you want to connect
port = 80
s.connect(('IP address of my server', port))
s.send(bytes("hand.jpeg","utf-8"))
f=open("back.jpeg","rb")
data=f.read(512)
while data:
s.send(data)
data=f.read(512)
f.close()
print(s.recv(10))
The server does not send any acknowledgement and seems to get stuck in the for loop. But if i remove the line c.send(bytes('Thank you ! File received.',"utf-8")) from the server script, the code works well. Also, if I remove the receive part from server side and just send the acknowledgent part , i.e c.send(bytes('Thank you ! File received.',"utf-8")) , the client receives the message. But If a combination of receive(the image file) and the acknowledgement is made in the server side as shown in the code, the server side fails to respond.
Important thing to note is that on KeyBoardInterrupt-ing the above program, it shows that the server side script is hanged/stuck in the data=c.recv(1024) line. But the same problem vanishes if the acknowledgement line is removed.
Note:- The client side script is running on my local machine and the server side script is running on a Google Cloud VM Instance.
Please help.
Thank you.
Hmm... I don't think I completely believe your description of the behavior. But I do know what's wrong. It's entirely reasonable that your server is sitting in the receive loop, because the client hasn't signaled EOF to the connection. Under what circumstances do you believe that this will actually break?
if not data:
break
The answer is that the client needs to either close the socket, or use shutdown(SHUT_WR) to indicate that it will not be sending any more data. So to do what you want, on the client side:
...
f.close()
s.shutdown(socket.SHUT_WR)
...
Now the next time the server calls recv, it will get an empty string returned and the break above will be taken.
This leaves the connection open in one direction but not the other. So the client will not be able to send any more data. However, the server will still be able to send to the client until it closes the socket (or uses shutdown itself).
There is another more subtle problem. You are assuming that your first server-side recv will receive only and exactly the bytes containing your file name. 99.9% of the time that will work. But it's possible that the data from your next client-side send will also be available when the server calls recv for the first time. That will likely give you a bogus file name (though not necessarily an illegal one) and will certainly mean that your file is not transferred faithfully.
You should never assume that the data provided by a single send by one peer will be received by a corresponding single recv on the other side. The data received could be more or less and it's up to the application to frame the data to ensure that it receives exactly the intended amount.
Here
while True:
data=c.recv(1024)
if not data:
break
f.write(data)
it loops back to waiting for a message after it has received one because you don't break the while loop after receiving data. the if not data: doesn't do anything since recv() stops and waits until it gets a message, and thus data is never nothing. You should either break the loop after receiving a message by adding a break after f.write(data), or send the OK in the loop.