I'm trying to use xinetd to remotely run a command (traccejob). When I connect through telnet, everything works fine. Unfortuantely, the client that I've written doesn't seem to receive the data from the server. The code looks like:
server:
import sys
import commands
def main():
tjinput = sys.stdin.readline().strip()
(ret, out) = commands.getstatusoutput('/usr/bin/tracejob '+tjinput)
print out
sys.stdout.flush()
if __name__ == "__main__":
main()
client:
host = 'xxx.xxx.xxx.xxx'
port = 12345
import socket
import sys
def main(argv):
message = 'hello'
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((host, port))
sock.send(message)
data = sock.recv(1024)
sock.close()
print repr(data)
if __name__ == '__main__':
main(sys.argv)
The client process stops on the sock.recv(1024) line. I can't for the life of me tell why sock.recv isn't reading the output from the socket. Probably a coding issue? If it helps, the xinetd.d file looks like this:
service tracejob
{
flags = IPv4
disable = no
socket_type = stream
wait = no
user = root
group = root
server = /usr/local/bin/tracejob_xinetd.py
port = 12345
type = UNLISTED
}
where tracejob_xinetd.py is the server described above.
Any tips? Thanks in advance.
You have a deadlock situation: The client sends an incomplete line and waits for the server to send something, the server waits for line completion or EOF before it sends a reply.
So you have now 2 ways to proceed now:
Append a \n to the string being sent.
"Half-close" the socket on client side with sock.shutdown(socket.SHUT_WR) after writing, but before reading.
Related
I'm new to socket programming in Python and I'm trying to write a chatroom application, but I have a problem which is it each client should press enter in order to receive messages from other clients.
#my client side code
import socket
import sys
client_sock = socket.socket()
port = int(sys.argv[1])
client_sock.connect(('127.0.0.1', port))
print("Connected to server. start sending messages")
while True:
sending_message = input('> ')
if sending_message:
client_sock.send(sending_message.encode())
receiving_message = client_sock.recv(1024)
if receiving_message:
print(receiving_message.decode())
input pauses your program. Thus, either you can't use input blindly, or you have to use threads. Using threads is easier than the alternative (using select to figure out what to do next). Have one thread for input and sending, one thread for receiving and printing.
Here's a trivial rewrite of your code:
import threading
import socket
import sys
client_sock = socket.socket()
port = int(sys.argv[1])
client_sock.connect(('127.0.0.1', port))
print("Connected to server. start sending messages")
def sender():
while True:
sending_message = input('> ')
if sending_message:
client_sock.send(sending_message.encode())
def receiver():
while True:
receiving_message = client_sock.recv(1024)
if receiving_message:
print(receiving_message.decode())
sender_thread = threading.Thread(target=sender)
receiver_thread = threading.Thread(target=receiver)
sender_thread.start()
receiver_thread.start()
sender_thread.join()
receiver_thread.join()
I am trying to make a server-client program using threads to handle each client, but the server will only accept one client at a time. If the first client disconnects, then the second client is accepted. Furthermore, each client can only send data once, then the program fails to send any more.
Prior to posting, I have looked at MANY other Stack Overflow posts, including the following:
how can I make a server communicate with more than 1 client at the same time?
python multithreaded server
My Python socket server can only receive one message from the client
But through looking at these posts I have found no solution.
Here is the server code:
import socket
from threading import *
def main():
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('172.20.3.62', 5000))
s.listen(1)
clients = []
print("listening")
def clienthandler(c):
clients.append(c)
try:
while True:
data = c.recv(1024).decode("UTF-8")
if not data:
break
else:
print(data)
for client in clients:
client.send(data.encode("UTF-8"))
except:
clients.remove(c)
c.close()
while True:
c, addr = s.accept()
print("accepted a client")
Thread(target=clienthandler(c)).start()
if __name__ == '__main__':
main()
Here is the client code:
import socket
from threading import *
def main():
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('172.20.3.62', 5000))
print("connected")
def send():
msg = input("ENTER:")
s.send(msg.encode("UTF-8"))
def receive():
while True:
data = s.recv(1024).decode("UTF-8")
if data:
print(data)
else:
break
Thread(target=send).start()
Thread(target=receive).start()
if __name__ == '__main__':
main()
Thanks to user Rawing. His/Her solution was: Thread(target=clienthandler(c)) -> Thread(target=clienthandler, args=(c,))
This allowed for more than one thread, and I was able to solve the only one message problem by putting the client send block in a while loop.
I have recently starting learning network programming with python. Here is a simple server I tried to write:
import socket
def server():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('127.0.0.1', 1024))
while True:
data, address = sock.recvfrom(65535)
text = data.decode('ascii')
print('the client from {0} sent: "{1}"'.format(address, text))
if text is '0': break
I wanted the server to wait till it is getting packets from the server, but when I run it, it will close instantly.
what did I do wrong?
You're not actually calling server().
Add this after the function definition:
if __name__ == '__main__':
server()
import select
import socket
import sys
host = ''
port = 50000
backlog = 5
size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host,port))
server.listen(5)
input = [server,sys.stdin]
running = 1
while running:
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == server:
# handle the server socket
client, address = server.accept()
input.append(client)
elif s == sys.stdin:
# handle standard input
junk = sys.stdin.readline()
running = 0
else:
# handle all other sockets
data = s.recv(size)
if data:
s.send(data)
else:
s.close()
input.remove(s)
server.close()
Whenever I run this code, I get this error message for my argument for the while loop:
inputready,outputready,exceptready = select.select(input,[],[])
TypeError: argument must be an int, or have a fileno() method.
How can I fix this to make the server run properly? Sorry if this is a bad question, I'm new to python and I can't figure this out. Thanks.
Yeah found the solution to your problem their seem to be sys.stdin , the python IDLE GUI for some reason doesn't allow you to use sys.stdin.fileno() in your code, while if you run it in the command prompt or the terminal it will work fine on linux. Link
An if your using windows, you cant pass the sys.stdin as an argument to the select() function, as in windows it accepts only sockets as arguments. As Explained in the documentation Documentation
Note: File objects on Windows are not acceptable, but sockets are. On Windows, the underlying select() function is provided by the WinSock library, and does not handle file descriptors that don’t originate from WinSock.
So to mitigate the problem , such that it works on both windows and linux:
import select
import socket
import sys
host = ''
port = 50000
backlog = 5
size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host,port))
server.listen(backlog)
input1 = [server]
running = 1
while running:
inputready,outputready,exceptready = select.select(input1,[],[])
for s in inputready:
if s == server:
# handle the server socket
client, address = server.accept()
input1.append(client)
elif s == sys.stdin:
# handle standard input
junk = sys.stdin.readline()
running = 0
else:
# handle all other sockets
data = s.recv(size)
if data:
s.send(data)
else:
s.close()
input1.remove(s)
server.close()
I'm new to using Python and sockets in general (only started yesterday) so I've been having a lot of issues trying to set up a TCP client and server. The issue I'm having is that I want to send a key from the server to the client. I know that the server grabs the key correctly as it prints out the correct key, however it has a 0 appended to it in a new line and when the key is sent to the client the only thing that is displayed is " b'0' ".
I've made very little progress due to my lack of experience and after searching for hours I still haven't found a solution to my problem.
Here is the server code:
import os
from socket import * #import the socket library
HOST = '' #We are the host
PORT = 29876
ADDR = (HOST, PORT)
BUFFSIZE = 4096
message = 'Hello, World!'
serv = socket( AF_INET,SOCK_STREAM)
serv.bind(ADDR,)
serv.listen(5)
print ('listening...')
conn,addr = serv.accept()
print (conn,addr)
print ('...connected')
key = os.system("cat ~/.ssh/id_rsa.pub")
conn.send(str(key))
print (key)
conn.close()
Here is the client code
from socket import *
import os
HOST = 'xxx.xxx.xxx.xxx'
PORT = 29876
ADDR = (HOST,PORT)
BUFFSIZE = 4096
message = "Hello, World!"
cli = socket( AF_INET, SOCK_STREAM)
cli.connect(ADDR,)
data = cli.recv(BUFFSIZE)
print (data)
cli.close()
As you can tell from my code I'm using Python 3.3
Any help with this issue is greatly appreciated.
os.system() does not return the process's output, but the return value (ie. integer 0).
If you only want to read a file, do it manually:
with open(os.path.expanduser("~/.ssh/id_rsa.pub")) as f:
key = f.read()
conn.sendall(key)
If you need process output, read the documentation for the subprocess module.