So, im trying to make a little program which shows message boxes with messages i send it. and it works, but when i clientside close the connection the server script exits and i get this message:
Traceback (most recent call last): File "server.py", line 9, in <module>
conn, addr = s.accept() File "C:\Python27\lib\socket.py", line 206, in accept
sock, addr = self._sock.accept() KeyboardInterrupt
this is my python code:
import socket
from appJar import gui
HOST = '' # Symbolic name meaning all available interfaces
PORT = 1337 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
while 1:
data = conn.recv(1024)
if not data: break
app=gui("Besked fra Romeo")
app.addLabel("idk",data)
app.go()
how do i stop the server script from closing when i close my clientside script?
KeyboardInterrupt is just an exception. You should be able to catch it:
try:
# Your loop
except KeyboardInterrupt:
# Code that gets executed when ctrl-c is pressed
Related
I know there is a similar question already, but none of the solutions solve my problem. Over ssh I am starting a script on a remote client with
nohup python script.py &
This script contains the following:
TCP_PORT = 5005
host = ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.settimeout(40)
s.bind((host, TCP_PORT))
s.listen(0)
c, addr = s.accept()
...some code...
try:
while True:
c.send(str(1).ljust(16).encode())
except Exception as e:
print("exiting main")
print(e)
c.close()
s.close()
When I run the code two times in e row, the second time I always get the above mentioned error. The log of the python output:
exiting main
[Errno 32] Broken pipe
Traceback (most recent call last):
File "LogImages.py", line 204, in <module>
main(interv)
File "LogImages.py", line 114, in main
s.bind((host, TCP_PORT))
OSError: [Errno 98] Address already in use
So obviously the process calls c.close() and s.close(). So how can the address still be in use?
Closing a socket just releases the handle to any underlying connection. It can still take the implementation some amount of time to complete the orderly shutdown of the connection and, during that time, the address is still in use.
For example, if you have an active connection and the other side isn't reading from it, the implementation will give it time to read the data that was sent. During that time, the address is still in use.
I recently ventured into python in 3.7
I want to make a server / client whose client will show the path I put in input (macOS):
Server
import socket
HOST = '' # Symbolic name meaning all available interfaces
PORT = 1337 # Arbitrary non-privileged port
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
with conn:
print('Connected by', addr)
info = conn.recv(1024)
print(info)
raw_input("Push to exit")
s.close()
Client :
import socket
import os
HOST = '' # The remote host
PORT = 1337 # The same port as used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
print('Connected')
info = os.listdir("/Users/jhon")
s.send(str(info))
s.close()
Server start and it's listening...
python client.py Connected Traceback (most recent call last): File
"client.py", line 10, in
s.send(str(info)) TypeError: a bytes-like object is required, not 'str' (not understand this), and after client start, in server show:
Connected by ('127.0.0.1', 52155) b'' Traceback (most recent call
last): File "server.py", line 13, in
raw_input("press for exit") NameError: name 'raw_input' is not defined (venv) MBP-di-Jhon:untitled1 jhon$
You may want to change the client code to:
HOST = '' # The remote host
PORT = 1337 # The same port as used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
print('Connected')
info = "\n".join(os.listdir("/Users/jhon"))
s.send(info.encode())
s.send(info)
s.close()
os.listdir("/Users/jhon") returns a list, we use join and encode to make it byte object, which is needed for s.send()
You ventured into 3.7 from some 2.x version without modifying the 2.x code. Read something about the differences before continuing. To help you get started:
Replace raw_input with input. (One could replace 2.x input() with eval(input()), but one should nearly always use a more specific evaluator, such as int(input()).)
In 3.x, strings are unicode, whereas sockets still require bytes. Change send and recv to
s.send(str(info).encode())
info = conn.recv(1024).decode()
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?
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()
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...