Subprocess results in "Broken Pipe" error - python-3.x

I'm playing around with socket programming. In the following code snippet I'm trying to connect to client and if his input contains "hack" it will remove it and run shell command and sends back the output.
server side:
import socket
class SP:
def server(self):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 9999))
s.listen(1)
while True:
try:
c, addr = s.accept()
print('Got connection from ', addr)
while True:
data = c.recv(1024)
if data:
if 'hack' in data.decode('utf-8'):
import subprocess
data = data.decode('utf-8')
data = data.strip('hack').lstrip().rstrip()
output = subprocess.call(data, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
s.send(str(output).encode('utf-8'))
else:
d = data.decode('utf-8')
print('Got data: '+str(d))
c.send(str('ACK: '+str(d)+' ...').encode('utf-8'))
else:
print('No more data from client: '+str(addr))
break
finally:
s.close()
except Exception as e:
print('Caught Exception: '+str(e))
s.close()
obj = SP()
obj.server()
client-side:
import socket
class CS:
def client(self):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 9999))
while True:
data = input('Enter data to be sent to server: \n')
if not data:
break
else:
s.send(data.encode('utf-8'))
reply = s.recv(1024).decode('utf-8')
print(str(reply))
else:
s.close()
except Exception as e:
print('Caught Exception: '+ str(e))
s.close()
obj = CS()
obj.client()
How can I resolve this the error ? Caught Exception: [Errno 32] Broken pipe doesn't tell me much.
update:
import socket
class SP:
def server(self):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 9999))
s.listen(1)
while True:
try:
c, addr = s.accept()
print('Got connection from ', addr)
while True:
data = c.recv(1024)
if data:
if 'hack' in data.decode('utf-8'):
import subprocess
data = data.decode('utf-8')
data = data.strip('hack').lstrip().rstrip()
print(data)
#output = subprocess.call(data, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
s.send(data.encode('utf-8'))
else:
d = data.decode('utf-8')
print('Got data: '+str(d))
c.send(str('ACK: '+str(d)+' ...').encode('utf-8'))
else:
print('No more data from client: '+str(addr))
break
finally:
s.close()
except Exception as e:
print('Caught Exception: '+str(e))
s.close()
obj = SP()
obj.server()
Even when I comment out the line where I call subprocess.call I still get "Broken Pipe" so the error isn't originating from the subprocess call.

You're using server's socket s instead of client's socket c to send the data to the client:
s.send(data.encode('utf-8'))
how about changing it to:
c.send(data.encode('utf-8'))

Related

SyntaxError: invalid syntax for listen() in python socket programming

The following is the code to transfer file from Server. I am getting and error saying
Error
s.listen(2)
^
SyntaxError: invalid syntax
Server code
import socket
import threading
import os
def RetrFile(name,sock):
filename = sock.recv(1024)
if os.path.isfile(filename):
sock.send("EXISTS " + str(os.path.getsize(filename)))
userResponse = sock.recv(1024)
if userResponse[:2] == 'OK':
with open(filename,'rb') as f:
bytesToSend = f.read(1024)
sock.send(bytesToSend)
while bytesToSend != "":
bytesToSend = f.read(1024)
sock.send(bytesToSend)
else:
sock.send("ERR")
sock.close()
def Main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(),1235)
s.listen(2)
print("Server started")
while True:
c,addr = s.accept()
print("Client connected ip:<" + str(addr) + ">")
t = threading.Thread(target = RetrFile, arfs=("retrThread", c))
t.start()
s.close()
if __name__ = '__main__':
Main()
Can someone help me out to understand why am I getting this error? I am new to python and socket programming.
This line is missing the closing parenthesis of the tuple:
s.bind((socket.gethostname(),1235)

Why isnt my python socket server receiving the messages?

so i am making a chatroom in python using sockets for practice. I have made the server code using threading so that i can have more clients. Ive also made the client code, and when i try to run two clients at once so that they message from one to another, they connect to server, but the server doesnt seem to be receiving the message sent from either of the clients.
SERVER CODE:
import select
from threading import *
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# takes the first argument from command prompt as IP address
IP_address = "127.0.0.1"
# takes second argument from command prompt as port number
Port = int("50204")
server.bind((IP_address, Port))
server.listen(1000)
list_of_clients = []
def clientthread(conn, addr):
# sends a message to the client whose user object is conn
conn.send("Welcome to this chatroom!")
while True:
try:
message = conn.recv(4096)
if message:
print("<" + addr[0] + "> " + message.decode("UTF-8"))
# Calls broadcast function to send message to all
message_to_send = "<" + addr[0] + "> " + message
broadcast(message_to_send.encode("UTF-8"), conn)
else:
remove(conn)
except:
continue
def broadcast(message, connection):
for clients in list_of_clients:
if clients != connection:
try:
clients.send(message)
except:
clients.close()
# if the link is broken, we remove the client
remove(clients)
def remove(connection):
if connection in list_of_clients:
list_of_clients.remove(connection)
while True:
conn, addr = server.accept()
list_of_clients.append(conn)
# prints the address of the user that just connected
print(addr[0] + " connected")
# creates and individual thread for every user
# that connects
Thread(target=clientthread, args=(conn, addr))
conn.close()
server.close()
CLIENT CODE:
import socket
import sys
import time
class client:
def __init__(self):
self.server_ip = "127.0.0.1"
self.port = 50204
self.s = self.connect()
def connect(self):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print("Failed to create socket.")
sys.exit()
print("Socket created")
try:
s.connect((self.server_ip, self.port))
except socket.error:
print("Failed to connect to ip " + self.server_ip)
print("Connected to: " + str(s.getsockname()))
return s
def SocketQuery(self, Sock, cmd):
try:
try:
# Send cmd string
Sock.send(cmd)
print("Sent!")
time.sleep(1)
except socket.error:
# Send failed
print("Send failed!")
sys.exit()
reply = Sock.recv(4096)
return reply
except ConnectionResetError:
print("Server is down!")
def SocketClose(self, Sock):
# close the socket
Sock.close()
time.sleep(.300)
if __name__ == "__main__":
c = client()
c.connect()
print("connected")
while True:
inp = input(">>> ")
if inp == ":q":
break
reply = c.SocketQuery(c.s, inp.encode("UTF-8"))
if reply:
print(reply.decode("UTF-8"))
c.SocketClose(c.s)
So as i have already mentioned, they do connect, but dont send/receive messages.
i have checked the value in conn.recv(), and it is the same, also everything gets encoded to UTF-8 before sent, and then decoded back. I cant seem to find any other problem except that im running them all on localhost.
If anyone knows the answer to this, please tell me.
cheers!

Socket server - readlines() function causes my program to stop/stuck

I'm trying a example to create a simple socket server, I need to receive multiline data from clients so this is my code for the socket server:
import socket
import sys
host = 'localhost'
port = 5006
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
c.bind((host, port))
c.listen(1)
while True:
try:
print("1")
csock, caddr = c.accept()
print("2")
with csock.makefile('rw', 2**16) as cfile:
print("3")
print(cfile.readline()) // When I use readline, it goes ok, but only get the first line, I need every line from data sent by client
print("4")
cfile.close()
print("5")
print("5.5")
csock.sendall("OK".encode('UTF-8'))
print("6")
csock.close()
print("7")
except KeyboardInterrupt:
print("Keyboard exit")
if 'csock' in locals():
csock.close()
sys.exit()
except Exception as e:
print(e)
Now when I use readlines(), my program just stuck and "does nothing" after print("3")
I tried with read() too, but still stuck, keep waiting both client and server
This is the code I'm using for client:
import socket
def query(host, port):
msg = \
'MSH|^~\&|REC APP|REC FAC|SEND APP|SEND FAC|20110708163513||QBP^Q22^QBP_Q21|111069|D|2.5|||||ITA||EN\r' \
'QPD|IHE PDQ Query|111069|#PID.5.2^SMITH||||\r' \
'RCP|I|'
# establish the connection
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((host, port))
# send the message
sock.sendall(msg.encode('UTF-8'))
# receive the answer
received = sock.recv(1024*1024)
return received
finally:
sock.close()
if __name__ == '__main__':
res = query('localhost', 5006)
print("Received response: ")
print(repr(res))
When I use readlines() and stop client after executing, server prints full message sent, I'm confused

NameError with echo client/server test: client unable to send custom message to the server

I'm learning python 3 and is my first language, so sorry if it's a silly question, but I cant't find out why it doesn't work...
I'm testing a simple echo client/server application. According to my book, I first created a file named tincanchat:
import socket
HOST = ''
PORT = 4040
def create_listen_socket(host, port):
""" Setup the sockets our server will receive connection
requests on """
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((host, port))
sock.listen(100)
return sock
def recv_msg(sock):
""" Wait for data to arrive on the socket, then parse into
messages using b'\0' as message delimiter """
data = bytearray()
msg = ''
# Repeatedly read 4096 bytes off the socket, storing the bytes
# in data until we see a delimiter
while not msg:
recvd = sock.recv(4096)
if not recvd:
# Socket has been closed prematurely
raise ConnectionError()
data = data + recvd
if b'\0' in recvd:
# we know from our protocol rules that we only send
# one message per connection, so b'\0' will always be
# the last character
msg = data.rstrip(b'\0')
msg = msg.decode('utf-8')
return msg
def prep_msg(msg):
""" Prepare a string to be sent as a message """
msg += '\0'
return msg.encode('utf-8')
def send_msg(sock, msg):
""" Send a string over a socket, preparing it first """
data = prep_msg(msg)
sock.sendall(data)
Then, I wrote the server:
import tincanchat
HOST = tincanchat.HOST
PORT = tincanchat.PORT
def handle_client(sock, addr):
""" Receive data from the client via sock and echo it back """
try:
msg = tincanchat.recv_msg(sock) # Blocks until received
# complete message
print('{}: {}'.format(addr, msg))
tincanchat.send_msg(sock, msg) # Blocks until sent
except (ConnectionError, BrokenPipeError):
print('Socket error')
finally:
print('Closed connection to {}'.format(addr))
sock.close()
if __name__ == '__main__':
listen_sock = tincanchat.create_listen_socket(HOST, PORT)
addr = listen_sock.getsockname()
print('Listening on {}'.format(addr))
while True:
client_sock, addr = listen_sock.accept()
print('Connection from {}'.format(addr))
handle_client(client_sock, addr)
And the client:
import sys, socket
import tincanchat
HOST = sys.argv[-1] if len(sys.argv) > 1 else '127.0.0.1'
PORT = tincanchat.PORT
if __name__ == '__main__':
while True:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
print('\nConnected to {}:{}'.format(HOST, PORT))
print("Type message, enter to send, 'q' to quit")
msg = input()
if msg == 'q': break
tincanchat.send_msg(sock, msg) # Blocks until sent
print('Sent message: {}'.format(msg))
msg = tincanchat.recv_msg(sock) # Block until
# received complete
# message
print('Received echo: ' + msg)
except ConnectionError:
print('Socket error')
break
finally:
sock.close()
print('Closed connection to server\n')
I run the server, then the client, which connects with the server and asks for input. At this point, it returns this error:
Connected to 127.0.0.1:4040
Type message, enter to send, 'q' to quit
Hello
Closed connection to server
Traceback (most recent call last):
File "C:\xxxxxxxxx\1.2-echo_client-uni.py", line 22, in <module>
except ConnectionError:
NameError: name 'ConnectionError' is not defined
Where is the problem?
Thanks in advance :)
If u want to catch the specified Errors or Exceptions, U should import them first.
What you could do for for example is:
from requests.exceptions import ConnectionError
try:
r = requests.get("http://example.com", timeout=0.001)
except ConnectionError as e: # This is the correct syntax
print e
r = "No response"
In this case your program will not return 'NameError'

Stop server from client's thread / Modify server's variable from client's thread

I would like to write an application that could stop the server based on client's input. The server is multi-threaded and I do not understand how can I do this.
Basically, I described my problem here: Modify server's variable from client's thread (threading, python).
However, this is the Python solution, not the general solution I could implement in Java, C, C++, etc.
I need to close other clients, when one of them guesses the number, but the server should be still alive, ready for the new game.
Can I ask for some advices, explanations?
I tried this (still do not know how to port it to C or Java), but it lets the clients send the numbers even if one of them just guesses it. It seems to me that kill_em_all does not do it's job, it does not close all the connections and does not disconnect the other clients as it should. How to improve this?
#!/usr/bin/env python
from random import randint
import socket, select
from time import gmtime, strftime
import threading
import sys
class Handler(threading.Thread):
def __init__(self, connection, randomnumber, server):
threading.Thread.__init__(self)
self.connection = connection
self.randomnumber = randomnumber
self.server = server
def run(self):
while True:
try:
data = self.connection.recv(1024)
if data:
print(data)
try:
num = int(data)
if self.server.guess(num) :
print 'someone guessed!'
self.server.kill_em_all()
break
else :
msg = "Try again!"
self.connection.sendall(msg.encode())
except ValueError as e:
msg = "%s" % e
self.connection.sendall(msg.encode())
else:
msg = "error"
self.connection.send(msg.encode())
except socket.error:
break
self.connection.close()
def send(self, msg):
self.connection.sendall(msg)
def close(self):
self.connection.close()
class Server:
randnum = randint(1,100)
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.address = (self.ip, self.port)
self.server_socket = None
def guess(self, no):
if self.randnum == no:
self.randnum = randint(1, 100)
print("New number is ", self.randnum )
result = True
else:
result = False
return result
def kill_em_all(self):
for c in self.clients:
c.send("BYE!")
c.close()
def run(self):
try:
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind((self.ip, self.port))
self.server_socket.listen(10)
self.clients = []
print('Num is %s' % self.randnum)
while True:
connection, (ip, port) = self.server_socket.accept()
c = Handler(connection, self.randnum, self)
c.start()
self.clients.append(c)
except socket.error as e:
if self.server_socket:
self.server_socket.close()
sys.exit(1)
if __name__ == '__main__':
s = Server('127.0.0.1', 7777)
s.run()
Client code:
import socket
import sys
port = 7777
s = None
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
s.connect(('127.0.0.1', port))
except socket.error, (value, message):
if s:
s.close()
print "Could not open socket: " + message
sys.exit(1)
while True:
data = raw_input('> ')
s.sendall(data)
data = s.recv(1024)
if data:
if data == "BYE!":
break
else:
print "Server sent: %s " % data
s.close()
Log in. Using whatever protocol you have, send the server a message telliing it to shut down. In the server, terminate your app when you get the shutdown message. That's it. It's not a problem with any OS I have used - any thread of a process can terminate that process.

Resources