Server crashes when the client is closing - python

I have encountered this problem earlier today. This is my first network application.
server.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
s = socket.socket()
host = socket.gethostname()
# Reserve a port for your service.
port = 12345
# Bind to the port
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
# Now wait for client connection.
s.listen(1)
conn, addr = s.accept()
try:
while True:
# connection, address
content = conn.recv(1024)
if content in ('status', 'stop', 'start', 'reload', 'restart'):
conn.send('%s received' % content)
else:
conn.send('Invalid command')
except KeyboardInterrupt:
conn.close()
s.shutdown(socket.SHUT_RDWR)
s.close()
client.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.connect((host, port))
try:
while True:
print ''
value = raw_input('Enter a command:\n')
if value != '':
s.send(value)
print s.recv(1024)
except KeyboardInterrupt:
s.shutdown(socket.SHUT_RDWR)
s.close()
It is a very basic client/server application. The server starts up, and wait for
the client to send commands. The client connects to the server, asks the user to
type a command. Commands are then sent to the server which replies <command>
received or Invalid command.
The code was running fine, until I hit CTRL+C. The server crashed. Why is that ?
Example:
python client.py
Enter a command:
stop
stop received
Enter a command:
status
status received
Enter a command:
bla
Invalid command
Enter a command:
^C
On the server side:
python server.py
Traceback (most recent call last):
File "server.py", line 25, in <module>
conn.send('Invalid command')
socket.error: [Errno 32] Broken pipe

Put your accept in a while loop, too. Something like:
while True:
conn, addr = s.accept() # accept one connection.
while True: # Receive until client closes.
content = conn.recv(1024) # waits to receive something.
if not content: # Receive nothing? client closed connection,
break # so exit loop to close connection.
if content in ('status', 'stop', 'start', 'reload', 'restart'):
conn.send('%s received' % content)
else:
conn.send('Invalid command')
conn.close() # close the connection
Also note recv returns empty string when the client closes the connection, hence the if not content: break.

Basically, I wasn't recreating a new connection on my server for new future clients, and then, when it was hitting the line conn.send('Invalid command'), it was crashing. To solve this:
I just replaced:
conn.send('Invalid command')
with:
try:
conn.send('Invalid command')
except socket.error:
conn, addr = s.accept()

Related

Python sockets. OSError: [Errno 9] Bad file descriptor

It's my client:
#CLIENT
import socket
conne = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conne.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
i=0
while True:
conne.connect ( ('127.0.0.1', 3001) )
if i==0:
conne.send(b"test")
i+=1
data = conne.recv(1024)
#print(data)
if data.decode("utf-8")=="0":
name = input("Write your name:\n")
conne.send(bytes(name, "utf-8"))
else:
text = input("Write text:\n")
conne.send(bytes(text, "utf-8"))
conne.close()
It's my server:
#SERVER
import socket
counter=0
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 3001))
sock.listen(10)
while True:
conn, addr = sock.accept()
data = conn.recv(1024)
if len(data.decode("utf-8"))>0:
if counter==0:
conn.send(b"0")
counter+=1
else:
conn.send(b"1")
counter+=1
else:
break
print("Zero")
conn.send("Slava")
conn.close()
))
After starting Client.py i get this error:
Traceback (most recent call last): File "client.py", line 10, in
conne.connect ( ('127.0.0.1', 3001) ) OSError: [Errno 9] Bad file descriptor
Problem will be created just after first input.
This program - chat. Server is waiting for messages. Client is sending.
There are a number of problems with the code, however, to address the one related to the traceback, a socket can not be reused once the connection is closed, i.e. you can not call socket.connect() on a closed socket. Instead you need to create a new socket each time, so move the socket creation code into the loop:
import socket
i=0
while True:
conne = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conne.connect(('127.0.0.1', 3001))
...
Setting socket option SO_BROADCAST on a stream socket has no affect so, unless you actually intended to use datagrams (UDP connection), you should remove the call to setsockopt().
At least one other problem is that the server closes the connection before the client sends the user's name to it. Probably there are other problems that you will find while debugging your code.
Check if 3001 port is still open.
You have given 'while True:' in the client script. Are you trying to connect to the server many times in an infinite loop?

TCP Chat server Python 3.4

There is an error in my client side code. The error is,"The operation was attempted on something that is not a socket." how do I go about fixing this error. I also know that my input is not sent to the server yet, If you guys have any tips on how I accomplish that I would also love them. Thanks! The code showed below:
import socket, select, string, sys
def prompt() :
sys.stdout.write('<You> ')
sys.stdout.flush()
#main function
if __name__ == "__main__":
host = "localhost"
port = 5000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
# connect to remote host
try :
s.connect((host, port))
except :
print('Unable to connect')
sys.exit()
print('Connected to remote host. Start sending messages')
prompt()
input = input()
while 1:
socket_list = [sys.stdin, s]
# Get the list sockets which are readable
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 chat server')
sys.exit()
else :
#print data
sys.stdout.write(data)
prompt()
#user entered a message
else :
msg = sys.stdin.readline()
s.send(msg)
prompt()
Server Code:
import socket, select
#Function to broadcast chat messages to all connected clients
def broadcast_data (sock, message):
#Do not send the message to master socket and the client who has send us the message
for socket in CONNECTION_LIST:
if socket != server_socket and socket != sock :
try :
socket.send(message)
except :
# broken socket connection may be, chat client pressed ctrl+c for example
socket.close()
CONNECTION_LIST.remove(socket)
if __name__ == "__main__":
# List to keep track of socket descriptors
CONNECTION_LIST = []
RECV_BUFFER = 4096 # Advisable to keep it as an exponent of 2
PORT = 5000
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# this has no effect, why ?
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(("0.0.0.0", PORT))
server_socket.listen(10)
# Add server socket to the list of readable connections
CONNECTION_LIST.append(server_socket)
print("Chat server started on port " + str(PORT))
while 1:
# Get the list sockets which are ready to be read through select
read_sockets,write_sockets,error_sockets = select.select(CONNECTION_LIST,[],[])
for sock in read_sockets:
#New connection
if sock == server_socket:
# Handle the case in which there is a new connection recieved through server_socket
sockfd, addr = server_socket.accept()
CONNECTION_LIST.append(sockfd)
print("Client (%s, %s) connected" % addr)
broadcast_data(sockfd, "[%s:%s] entered room\n" % addr)
#Some incoming message from a client
else:
# Data recieved from client, process it
try:
#In Windows, sometimes when a TCP program closes abruptly,
# a "Connection reset by peer" exception will be thrown
data = sock.recv(RECV_BUFFER)
if data:
broadcast_data(sock, "\r" + '<' + str(sock.getpeername()) + '> ' + data)
except:
broadcast_data(sock, "Client (%s, %s) is offline" % addr)
print("Client (%s, %s) is offline" % addr)
sock.close()
CONNECTION_LIST.remove(sock)
continue
server_socket.close()
On Microsoft Windows, python's socket library is implemented using Winsock. Winsock isn't integrated into the operating system like the sockets library on unixy systems. It has its own idea of what a socket is, and does not recognize system pipes or consoles.
On Windows you get the error you see
>>> import platform
>>> print platform.system()
Windows
>>> import socket
>>> import select
>>> import sys
>>> select.select([sys.stdin],[],[])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
select.error: (10038, 'An operation was attempted on something that is not a socket')
>>> select.select([sys.stdin.fileno()],[],[])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
select.error: (10038, 'An operation was attempted on something that is not a socket')
>>>
On linux it works
>>> import platform
>>> print platform.system()
Linux
>>> import socket
>>> import select
>>> import sys
>>> select.select([sys.stdin],[],[],0)
([], [], [])
>>>
I couldn't see anything wrong so I ran your code on my linux box with python3.4 and got no errors from either server or the client and they connected without issue. The only thing I can think of is with your version of python or OS like tdelaney suggested. I don't have a windows box to test with so I can't confirm if it's OS specific.
Use input = [s] #instead of socket_list = [sys.stdin, s]

Python Socket Scripting. What am i doing wrong?

My socket program hangs at clientsocket, address) = serversocket.accept() and doesn't spit our an error or anything.
I followed directions on https://docs.python.org/3/howto/sockets.html
I've been trying to figure it out for an hour now, but to no avail. I'm using python3 btw. What am i doing wrong? EDIT: My intedentation is all screwed up because I pasted it wrong, but other than that my code is as I have it in my file.
#import socket module
import socket
#creates an inet streaming socket.
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('socket created')
#binds socket to a public host, and a well known port
serversocket.bind(('127.0.0.1', 1024))
#print(socket.gethostname())# on desktop prints 'myname-PC')
#become a server socket
serversocket.listen(5) # listens for up to 5 requests
while True:
#accept connections from outside
#print('In while true loop') This works, but we never get to the next print statement. Why the hell is it catching at line 20?
(clientsocket, address) = serversocket.accept()
#clientsocket = serversocket.accept()
print('Ready to serve')
#now we do something with client socket...
try:
message = clientsocket.recv(1024)
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
#send an http header line
clientsocket.send('HTTP/1.1 200 OK\nContent-Type: text/html\n\n')
for i in range(0, len(outputdata)):
clientsocket.send(outputdata[i])
clientsocket.close()
except IOERROR:
clientsocket.send('HTTP/1.1 404 File not found!')
clientsocket.close()
If you haven't written a client script / program to connect to the socket and send it data, it's also going to hang on serversocket.accept() due to there being nothing to accept. But assuming you have...
while True:
#accept connections from outside
#print('In while true loop') This works, but we never get to the next print statement. Why the hell is it catching at line 20?
(clientsocket, address) = serversocket.accept()
#clientsocket = serversocket.accept()
It hangs because the loop never exits due to True always being True. In the example provided, once a connection is accepted they pretend that the server is threaded and the idea is to create a separate thread to begin reading and processing data received allowing the socket to continue to listen for more connections.
while True:
# accept connections from outside
(clientsocket, address) = serversocket.accept()
# now do something with the clientsocket
# in this case, we'll pretend this is a threaded server
ct = client_thread(clientsocket)
ct.run()

Python Server send data not working

I am currently working on a server in Python, the problem I am facing is the client could not retrieve the sent data from server.
The code of the server is:
import sys
import socket
from threading import Thread
allClients=[]
class Client(Thread):
def __init__(self,clientSocket):
Thread.__init__(self)
self.sockfd = clientSocket #socket client
self.name = ""
self.nickName = ""
def newClientConnect(self):
allClients.append(self.sockfd)
while True:
while True:
try:
rm= self.sockfd.recv(1024)
print rm
try:
self.sockfd.sendall("\n Test text to check send.")
print "Data send successfull"
break
except socket.error, e:
print "Could not send data"
break
except ValueError:
self.sockfd.send("\n Could not connect properly")
def run(self):
self.newClientConnect()
self.sockfd.close()
while True:
buff = self.sockfd.recv(1024)
if buff.strip() == 'quit':
self.sockfd.close()
break # Exit when break
else:
self.sendAll(buff)
#Main
if __name__ == "__main__":
#Server Connection to socket:
IP = '127.0.0.1'
PORT = 80
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
print ("Server Started")
try:
serversocket.bind(('',5000))
except ValueError,e:
print e
serversocket.listen(5)
while True:
(clientSocket, address) = serversocket.accept()
print 'New connection from ', address
ct = Client(clientSocket)
ct.start()
__all__ = ['allClients','Client']
#--
And the client connecting is:
import socket
HOST = '192.168.1.4' # The remote host
PORT = 5000 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
data = s.recv(1024)
s.close()
print 'Received', data#repr(data)
In need of a quick solution....
Thanks,
I tested out your code, and when I commented out
rm= self.sockfd.recv(1024)
print rm
it worked fine. Basically the server stopped there to wait for a message that never came. If it still does not work for you, there might be two problems. Either you have a firewall that blocks the connection somehow, or you have old servers running in the background from previous tries that actually wasn't killed. Check your processes if pythonw.exe or equivalent is running when it shouldn't be, and kill it.
To wait for response:
with s.makefile('rb') as f:
data = f.read() # block until the whole response is read
s.close()
There are multiple issues in your code:
nested while True without break
finally: ..close() is executed before except ValueError: ..send
multiple self.sockfd.close()
etc
Also you should probably use .sendall() instead of .send().
your server code is excepting client send something first,
rm= self.sockfd.recv(1024)
but I don't see any in your code
please try send something in your client code
s.connect((HOST, PORT))
s.send("hello")
Short solution
Add a short sleep after connect.
import time
time.sleep(3)

Python client / server question

I'm working on a bit of a project in python. I have a client and a server. The server listens for connections and once a connection is received it waits for input from the client. The idea is that the client can connect to the server and execute system commands such as ls and cat. This is my server code:
import sys, os, socket
host = ''
port = 50105
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print("Server started on port: ", port)
s.listen(5)
print("Server listening\n")
conn, addr = s.accept()
print 'New connection from ', addr
while (1):
rc = conn.recv(5)
pipe = os.popen(rc)
rl = pipe.readlines()
file = conn.makefile('w', 0)
file.writelines(rl[:-1])
file.close()
conn.close()
And this is my client code:
import sys, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = 'localhost'
port = input('Port: ')
s.connect((host, port))
cmd = raw_input('$ ')
s.send(cmd)
file = s.makefile('r', 0)
sys.stdout.writelines(file.readlines())
When I start the server I get the right output, saying the server is listening. But when I connect with my client and type a command the server exits with this error:
Traceback (most recent call last):
File "server.py", line 21, in <module>
rc = conn.recv(2)
File "/usr/lib/python2.6/socket.py", line 165, in _dummy
raise error(EBADF, 'Bad file descriptor')
socket.error: [Errno 9] Bad file descriptor
On the client side, I get the output of ls but the server gets screwed up.
Your code calls conn.close() and then loops back around to conn.recv(), but conn is already closed.
If you want your client to repeat what it's doing, just add a loop in there ;)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = 'localhost'
port = input('Port: ')
s.connect((host, port))
while True:
cmd = raw_input('$ ')
s.send(cmd)
file = s.makefile('r', 0)
sys.stdout.writelines(file.readlines())
Should probably be closer to what you want.
Other comments:
s.listen(1)
This statement should probably be moved outside of the while loop. You only need to call listen once.
pipe = os.popen(rc)
os.popen has been deprecated, use the subprocess module instead.
file = s.makefile('r', 0)
You're opening a file, yet you never close the file. You should probably add a file.close() after your sys.stdout.writelines() call.
EDIT: to answer below comment; done here due to length and formatting
As it stands, you read from the socket once, and then immediately close it. Thus, when the client goes to send the next command, it sees that the server closed the socket and indicates an error.
The solution is to change your server code so that it can handle receiving multiple commands. Note that this is solved by introducing another loop.
You need to wrap
rc = conn.recv(2)
pipe = os.popen(rc)
rl = pipe.readlines()
fl = conn.makefile('w', 0)
fl.writelines(rl[:-1])
in another while True: loop so that it repeats until the client disconnects, and then wrap that in a try-except block that catches the IOError that is thrown by conn.recv() when the client disconnects.
the try-except block should look like
try:
# the described above loop goes here
except IOError:
conn.close()
# execution continues on...

Categories

Resources