I have a twisted server script listening on a unix socket and it receives the data when the client is in twisted but it doesn't work if i send it via a vanilla python socket code.
class SendProtocol(LineReceiver):
"""
This works
"""
def connectionMade(self):
print 'sending log'
self.sendLine(self.factory.logMessage)
if __name__ == '__main__':
address = FilePath('/tmp/test.sock')
startLogging(sys.stdout)
clientFactory = ClientFactory()
clientFactory.logMessage = 'Dfgas35||This is a message from server'
clientFactory.protocol = SendProtocol
port = reactor.connectUNIX(address.path, clientFactory)
reactor.run()
But this doesn't (server doesn't get any data)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock_addr = '/tmp/test.sock'
try:
sock.connect(sock_addr)
except socket.error, msg:
print >> sys.stderr, msg
sys.exit(1)
sock.setblocking(0) # not needed though tried both ways
print 'connected %s' % sock.getpeername()
print 'End END to abort'
while True:
try:
line = raw_input('Enter mesg: ')
if line.strip() == 'END':
break
line += '\n'
print 'sending'
sock.sendall(line)
finally:
sock.close()
Your two client programs send different data. One sends \r\n-terminated lines. The other sends \n-terminated lines. Perhaps your server is expecting \r\n-terminated lines and this is why the latter example doesn't appear to work. Your non-Twisted example also closes the socket after the first line it sends but continues with its read-send loop.
Related
I'm trying to run a client/server script, where the client sends a file to the server and waits for responses until the server sends a stop message.
The problem is: once the connection is established the client starts sending data but until I press CTRL-C the server cannot recreate the file. Only after CTRL-C print "file is fully created" and the file becomes visible, instead, before it's seems to be waiting for something. idk where the problem is. Also tried changing condition on send loop using len(), but doesn't work. Anyone know how to fix it ?
client.py :
import socket # Import socket module
# from threading import Thread
s = socket.socket() # Create a socket object
HOST = "101.xx.x.xxx" # public IP address
PORT = 4243 # Reserve a port for your service.
PDF_PATH = "exam.pdf"
s.connect((HOST, PORT))
def send():
f = open(PDF_PATH, "rb")
while data := f.read(4096):
s.send(data)
f.close()
return
def receive():
while 1:
exercise = s.recv(4096)
if exercise == "stop!":
s.close()
break
f = open(f"{exercise}.txt", "wb")
while data := f.read(4096):
f.write(data)
return
def main():
send()
receive()
if __name__ == "__main__":
main()
server.py :
import socket
from threading import Thread
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
HOST = socket.gethostname()
IP = socket.gethostbyname(HOST)
PORT = 4243
s.bind(('', PORT))
s.listen(5)
def receive_file(conn, i):
f = open(f"exam.pdf", "wb")
while received := conn.recv(4096):
f.write(received)
print("File is fully copied\n")
f.close()
def send_result(conn,i):
while 1:
nbr = str(input("which exercise? "))
if nbr == "stop!":
break
f = open(f"exercise{nbr}.txt", "rb")
conn.send(bytes(f"exercise{nbr}.txt", encoding="utf-8"))
while data := f.read(4096):
conn.send(data)
f.close()
def main():
try:
while 1:
i = 0
conn, addr = s.accept()
print("Got connection from", addr)
# c.send(b"Thank you for connecting")
t = Thread(target=receive_file, args=(conn, i))
t.start()
t.join()
t = Thread(target=send_result, args=(conn, i))
t.start()
t.join()
except KeyboardInterrupt:
print("interrupting \n")
conn.close()
s.close()
if _name_ == '_main_':
main()
conn.recv() in the server won't return '' (no more data) unless the client closes the connection or calls shutdown(SHUT_WR) to indicate sends are complete:
def send():
with open(PDF_PATH, "rb") as f:
while data := f.read(4096):
s.sendall(data)
s.shutdown(socket.SHUT_WR)
An alternative is to design a protocol that sends the length of data before the data so you know when you've received the complete transmission. This would be required if you need to send more than one thing without closing the socket or shutting down sends. You're going to need this to make the receive portion of the server work if you want to send more than one exercise file.
Refer to this answer for an example of sending multiple files over a socket.
I've been looking and dealing with this issue for a week. I have client code that causes select() to return a socket that has actually closed from external reasons throwing an error 9 BAD FILE DESCRIPTOR, however I tested the code from a different python file and CANNOT get it to error. Ive tried a million things. heres a snippet from the server:
NOTE: This will work for a few iterations and then suddenly break, it errors out in the message_queue as key error due to the file descriptor breaking even tho a message/no message has a key for that socket present.
#Create the socket to communicate with uWSGI applications
server_address = ('localhost', 10001)
server = create_server_socket(server_address)
#Sockets which we expect to read on from select()
input_sockets = [server]
#Sockets which we expect to write to from select()
output_sockets = []
#Message buffer dicitonary for outgoing messages
message_queue = {}
#Now wait for connections endlessly
while input_sockets:
print >> sys.stderr, "Waiting for the next event..."
readable, writable, exceptional = select.select(input_sockets, output_sockets, input_sockets)
#Handle input_sockets
for s in readable:
#Server socket is available for reading now
if s is server:
#Create a connection and address object when incoming request is recieved
connection, client_addr = s.accept()
print >> sys.stderr, "Connection recieved from %s!" % (client_addr,)
#Set client connection to non blocking as well
connection.setblocking(0)
#Add this socket to input sockets as it will read for client data
input_sockets.append(connection)
#Give connection a queue for sending messages to it
message_queue[connection] = Queue.Queue()
#A client has sent data so we can handle its request
else:
#Pull data from the client
data = ""
try:
while True:
message = s.recv(1024)
if not message:
break
data += message
except Exception as e:
print str(e)
if data:
#Readable client socket has data
print >> sys.stderr, 'Recieved "%s" from %s' % (data, s.getpeername())
message_queue[s].put(data)
#Add output channel now to send message
if s not in output_sockets:
output_sockets.append(s)
#There is no data to be read, socket must be closed
else:
print >> sys.stderr, 'Closing', client_addr,'after recieving no data.'
#Stop listening for input on the socket
if s in output_sockets:
output_sockets.remove(s)
input_sockets.remove(s)
#Close the connection
s.close()
del message_queue[s]
#Handle writable connections
for s in writable:
if s:
try:
next_message = message_queue[s].get_nowait()
except:
print >> sys.stderr, 'No data to send for', s.getpeername()
output_sockets.remove(s)
else:
try:
print >> sys.stderr, 'Sending "%s" to %s' % (next_message, s.getpeername())
s.sendall(next_message)
except:
print >> sys.stderr, 'No data to send for', s.getpeername()
output_sockets.remove(s)
#s.sendall('EOF:!##$:EOF')
#Now handle any exceptions
for s in exceptional:
print >> sys.stderr, 'Handling exception on ', s.getpeername()
input_sockets.remove(s)
if s in output_sockets:
output_sockets.remove(s)
s.close()
#Remove any messages
del message_queue[s]
client:
messages = [ 'This is the message. ',
'It will be sent ',
'in parts.',
]
server_address = ('localhost', 10001)
# Create a TCP/IP socket
socks = [ socket.socket(socket.AF_INET, socket.SOCK_STREAM),
socket.socket(socket.AF_INET, socket.SOCK_STREAM),
]
# Connect the socket to the port where the server is listening
print >>sys.stderr, 'connecting to %s port %s' % server_address
for s in socks:
s.connect(server_address)
for message in messages:
# Send messages on both sockets
for s in socks:
print >>sys.stderr, '%s: sending "%s"' % (s.getsockname(), message)
s.send(message)
# Read responses on both sockets
for s in socks:
data = s.recv(1024)
print >>sys.stderr, '%s: received "%s"' % (s.getsockname(), data)
if not data:
print >>sys.stderr, 'closing socket', s.getsockname()
s.close()
NOTE: This client side is only to test and start passing messages.
There is a race in your code when a socket is returned as both readable and writable and you close the socket because the read returned 0 bytes. In this case you remove the socket from input_sockets, output_sockets and message_queue but the closed socket is still in writable and it will thus try to write to it inside the same iteration of the select loop.
I have no idea if this is the race you'll see because you neither show debug output not did you say where you stumble over this EBADF. To track similar problems down I recommend to augment your code with more debug information on where you close a socket and where you try to process a socket because it is readable or writable so that you actually find the exact place of the race when looking at the debug output.
Here is my server code.
# chat_server.py
import sys, socket, select
HOST = ''
SOCKET_LIST = []
RECV_BUFFER = 4096
PORT = 9009
def chat_server():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
# add server socket object to the list of readable connections
SOCKET_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
# 4th arg, time_out = 0 : poll and never block
ready_to_read,ready_to_write,in_error = select.select(SOCKET_LIST,[],[],0)
for sock in ready_to_read:
# a new connection request recieved
if sock == server_socket:
sockfd, addr = server_socket.accept()
SOCKET_LIST.append(sockfd)
print "Client (%s, %s) connected" % addr
broadcast(server_socket, sockfd, "[%s:%s] entered our chatting room\n" % addr)
# a message from a client, not a new connection
else:
# process data recieved from client,
try:
# receiving data from the socket.
data = sock.recv(RECV_BUFFER)
if data:
# there is something in the socket
broadcast(server_socket, sock, "\r" + '[' + str(sock.getpeername()) + '] ' + data)
else:
# remove the socket that's broken
if sock in SOCKET_LIST:
SOCKET_LIST.remove(sock)
# at this stage, no data means probably the connection has been broken
broadcast(server_socket, sock, "Client (%s, %s) is offline\n" % addr)
# exception
except:
broadcast(server_socket, sock, "Client (%s, %s) is offline\n" % addr)
continue
server_socket.close()
# broadcast chat messages to all connected clients
def broadcast (server_socket, sock, message):
for socket in SOCKET_LIST:
# send the message only to peer
if socket != server_socket and socket != sock :
try :
socket.send(message)
except :
# broken socket connection
socket.close()
# broken socket, remove it
if socket in SOCKET_LIST:
SOCKET_LIST.remove(socket)
if __name__ == "__main__":
sys.exit(chat_server())
Here is my client code.
# chat_client.py
import sys, socket, select
def chat_client():
if(len(sys.argv) < 3) :
print 'Usage : python chat_client.py hostname port'
sys.exit()
host = sys.argv[1]
port = int(sys.argv[2])
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()
# TEST
person = raw_input ('Please enter your username: ')
print 'Connected to remote host. You can start sending messages.'
sys.stdout.write( person + '[Me]: ' ); sys.stdout.flush()
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:
if sock == s:
# incoming message from remote server, s
data = sock.recv(4096)
if not data :
print '\nDisconnected from chat server'
sys.exit()
else :
#print data
sys.stdout.write(data)
sys.stdout.write( person + '[Me]: '); sys.stdout.flush()
else :
# user entered a message
msg = sys.stdin.readline()
s.send(msg)
sys.stdout.write( person + '[Me]: '); sys.stdout.flush()
if __name__ == "__main__":
sys.exit(chat_client())
I'm currently trying to work on adding sort of a "handle" system into the chat client. If you were to run this code, you'll notice that the handle you choose is only displayed on your client, and not anybody else's. I've done hours of research already, and I can't for the life of me figure out how to have a client's chosen handle displayed onto other clients.
I'm still relatively new to Python, and especially new to TCP/IP programming. Any help, advice, and constructive criticism will be welcomed. Thanks in advance!
You can do it on the server or the client side
Server side
To implement it server side, you need to maintain some kind of mapping in the server between client sockets and handles, so that when you broadcast a message from a socket, you can retrieve its handle and prepend it to the message before sending.
In order to know the handle of the clients, they can send it to the server as the first message when they connect. The server will interpret this first message as the handle, and store it mapping it to the socket from what it has been received.
The advantage of this approach is that the server can validate the handle before it accepts it from the clients, and if it is already in use, reject the handle or abort the connection. Also, the clients cannot fake their handle later in the conversation, as it is the server that sends them.
Client side
This is the easiest implementation, as you only need to modify the client and prepend the handle before sending each message.
# user entered a message
msg = sys.stdin.readline()
s.send(person + ": " + msg)
sys.stdout.write( person + '[Me]: '); sys.stdout.flush()
The drawbacks of this approach are that a malicious client can fake the handle to pretend to be another person, and that two clients can have the same handle at the same time, making them indistinguishable from each other.
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)
I have simple python server and client.
Server:
import SocketServer
import threading
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print str(self.client_address[0]) + " wrote: "
print self.data
self.request.send(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 3288
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
Client:
import socket
import sys
from time import sleep
HOST, PORT = "localhost", 3288
data = "hello"
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
sock.send(data + "\n")
received = sock.recv(1024)
sleep(10)
sock.send(data + "\n")
received = sock.recv(1024)
sleep(10)
sock.send(data + "\n")
received = sock.recv(1024)
finally:
sock.close()
Here is the output I get:
Server:
>python server.py
127.0.0.1 wrote:
hello
Client:
>python client.py
Traceback (most recent call last):
File "client.py", line 18, in <module>
received = sock.recv(1024)
socket.error: [Errno 10053] An established connection was aborted by the software in your host machine
I tried it on a linux machine as well. The server only receives one message and then I get an error on the recv statement of second message. I have just started learning networking on python but I think the server is closing the socket for some reason. How do I correct this?
A MyTcpHandler object is created for each connection, and handle is called to deal with the client. The connection is closed when handle returns, so you have to handle the complete communication from the client within the handle method:
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
while 1:
self.data = self.request.recv(1024)
if not self.data:
break
self.data = self.data.strip()
print str(self.client_address[0]) + " wrote: "
print self.data
self.request.send(self.data.upper())
NOTE: recv returns '' when the client closes the connection, so I moved .strip() after the recv so there is no false alarm due to the client sending only white space.
I'll first admit that it's been years since I last used SocketServer, so there might be more idiomatic approaches to solve your problem.
Note that your client opens a single connection and sends three sets of data and receives three sets of data. (Hopefully the TCP stack will send buffered data once you call receive() on the socket.)
Your server is expecting to handle a client connection completely, from start to finish, when it is called from the SocketServer callback mechanism. Your current class does a little bit of IO and then quits. You just need to extend your server callback to do more:
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print str(self.client_address[0]) + " wrote: "
print self.data
self.request.send(self.data.upper())
foo = self.request.recv(1024).strip()
self.request.send(foo.lower())
bar = self.request.recv(1024).strip()
self.request.send("goodbye " + bar)
TO a similar problem here error: [Errno 10053]
I also tried the same thing and got the same error.
If there is a simple code like this to demonstrate this error:
import socket
host = 'localhost'
port = 5001
size = 102400
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
for msg in ['Hello, world','Test','anything goes here']:
s.send(msg)
data = s.recv(size)
print 'Received:', data
s.close()
If you create a socket object and the amt it can send and echo back from server to see how much it receivers, if you vary that, say 1024 to 102400(in this code);
Which means the socket should not get closed but again in my Windows OS, the server side keeps listening and printing any data that client sends but on the Client side you get this error;
However if it is that the client can connect only once and send and receive only once, then that is how it was designed. Trying this works without any errors:
for msg in ['Hello, world','Test','anything goes here']:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.send(msg)
data = s.recv(size)
s.close()
print 'Received:', data
I am not sure if one socket object works only once to send and recieve data.
UPDATE
I think the issue was the capacity per client socket to receive data as per the buffersize fixed;
That's why the second code snippet above works thus creating new client connection sockets on the server. But that way lots of sockets are going to get used up.
Instead the following code fixed that problem by checking the amt of size being used up. If it exceeds the given amount, it creates a new socket at clients' but makes sure the message is sent; Actually the problem was with the server code but fixed it.
size = 10
This is a quick baby attempt at the code. I am sure you would understand and optimize it for the better!
client code:
messag = ['Hello, world', 'Test', 'anything goes here']
def client_to_server(messag,host,port,size):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
countmsg = 0
restmsg = ''
for msg in messag:
strl = tmsg = msg
if len(restmsg):
tmsg = restmsg + ' ' + msg
countmsg = len(tmsg)
if countmsg <= size:
pass
else:
restmsg = tmsg[size:]
tmsg = tmsg[:size]
#s.close()
countmsg = len(tmsg)
#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#s.connect((host, port))
print 'Sending to server msg {}'.format(tmsg)
s.send(tmsg)
# s.settimeout(1)
try:
data = s.recv(size)
print 'Received:', data
if strl == data:
print strl,data
countmsg = 0
restmsg = ''
except (socket.error), e:
print e.args,e.message
s.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.close()
if restmsg:
client_to_server([restmsg],host,port,size)
return
client_to_server(messag,host,port,size)
Server Code:
size = 1024 #This has to be bigger than client buf size!
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(backlog)
while True:
#this is what accepts and creates a P2P dedicated client socket per socket
client, address = s.accept()
try:
data = client.recv(size)
while data or 0:
print "Client sent {} | Server sending data to client address {}".format(data, address)
client.send(data)
data = client.recv(size)
else: client.close()
except (socket.error), e:
client.close()
print e.args, e.message
Try it out. This uses the same socket.