I am trying to send and receive data using TCP connection using Python. My server and client are in the same file, defined and used as follows.
In the constructor, I define the server as:
self.sock_in = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock_in.bind((self.host_ip, self.host_port))
self.sock_in.listen(1)
Do not worry about the host_ip and host_port variables, they are all fine.
In a function, I am trying to send data as follows:
sock_out = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP Connection
sock_out.connect((self.remote_ip, self.remote_port))
sock_out.send(self.navigation_data.get_message())
sock_out.close()
And this is my main:
def main(self):
rospy.logwarn("Starting...")
while not rospy.is_shutdown():
conn = self.sock_in.accept()
try:
recv_buffer = conn.recv(BUFFERSIZE_IN)
if recv_buffer != "":
msg = recv_buffer.decode('utf-8')
msg_type = msg[:msg.find(',')]
if msg_type == self.pilot_control.MESSAGE_ID:
self.pilot_control_handler(msg, self.pilot_control_publisher)
else:
rospy.logwarn("Received an unimplemented message type '%s'", msg_type)
except socket.error as socket_error:
rospy.logerr("SocketError: %s", str(socket_error))
And the error I get is:
line 230, in send_83b_package
sock_out.connect((self.remote_ip, self.remote_port))
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
error: [Errno 111] Connection refused
I put some print commands to see where it collapses, and apparently it does not run the accept command. Until there I can see the print commands working, but after the accept method nothing is printed, which means it collapses there.
I suspect the problem is about synchronization. That is, the server does not start fast enough.
Any thoughts?
EDIT:
One of the suggestions was to run the server on a separate thread, which I tried as follows:
def my_tcp_server(self):
# Establish a TCP Connection
self.sock_in = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock_in.bind((self.host_ip, self.host_port))
self.sock_in.listen(1)
rospy.logwarn("ready")
while not rospy.is_shutdown():
rospy.logwarn("before accept")
conn, address = self.sock_in.accept()
rospy.logwarn("after accept")
try:
recv_buffer = conn.recv(BUFFERSIZE_IN)
rospy.logwarn("recv works!")
if recv_buffer != "":
msg = recv_buffer.decode('utf-8')
msg_type = msg[:msg.find(',')]
if msg_type == self.pilot_control.MESSAGE_ID:
self.pilot_control_handler(msg, self.pilot_control_publisher)
else:
rospy.logwarn("Received an unimplemented message type '%s'", msg_type)
except socket.error as socket_error:
rospy.logerr("SocketError: %s", str(socket_error))
conn.close()
def main(self):
rospy.logwarn("Starting..")
threading.Thread(target=self.my_tcp_server).start()
And in my constructor, the order of calls are as follows:
self.main()
self.sendDataFunction()
Which should be okay. However, the accept function is still not working, hence there is no connection.
As you didn't provide a complete executable code example I took your snippet and removed the class declaration aspects, added definitions for ip/port etc. Also added socket timeout. Anywayt this code works for me on Windows 7x64 with 32-bit Python 2.7.8:
import threading
import socket
is_shutdown = False
BUFFERSIZE_IN = 32768
def my_tcp_server():
# Establish a TCP Connection
sock_in = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_in.bind((host_ip, host_port))
sock_in.settimeout(10000)
sock_in.listen(1)
print "ready"
while not is_shutdown:
print "before accept"
conn, address = sock_in.accept()
print "after accept"
try:
recv_buffer = conn.recv(BUFFERSIZE_IN)
print "recv works!"
if recv_buffer != "":
msg = recv_buffer.decode('utf-8')
print "Received",msg
except socket.error as socket_error:
print "SocketError: %s", str(socket_error)
conn.close()
print "Shutting down server"
sock_in.close()
def main():
print "Starting.."
threading.Thread(target=my_tcp_server).start()
def sendData():
sock_out = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP Connection
sock_out.connect((remote_ip, remote_port))
sock_out.send("ASD")
sock_out.close()
host_ip="127.0.0.1"
remote_ip = host_ip
host_port = 8073
remote_port = host_port
main()
print "Sending"
sendData()
print "Completed"
is_shutdown = True
The output is:
Starting..
Sending
ready
before accept
Completedafter accept
recv works!
Received ASD
Shutting down server
I guess there is something in your class/constructor/something I can't see which is making your code not work.
HTH
barny
Related
After that I have connected to the server from input, how do I change my server in the chat?
I just updated the code with something that could work though it needs some more work, anyone?
def send(event=None): # event is passed by binders.
"""Handles sending of messages."""
global HOST
global PORT
global ADDR
msg = my_msg.get()
my_msg.set("") # Clears input field.
msg_list1 = msg.split()
try:
if msg_list1 [0] == "/connect":
try:
HOST = msg_list1[1]
PORT = int(msg_list1[2])
ADDR = (HOST,PORT)
client_socket.connect(ADDR)
receive_thread = Thread(target=receive)
receive_thread.start()
except TypeError:
msg_list_tk.insert(tt.END, "Error: please write '/connect ADDR PORT' to connect to server\n")
if msg_list1 [0] == "/connectnew":
HOST = msg_list1[1]
PORT = int(msg_list1[2])
ADDR = (HOST,PORT)
client_socket_2.connect(ADDR)
receive_thread = Thread(target=receive)
receive_thread.start()
except:
msg_list_tk.insert(tt.END, "Error: please write '/connect ADDR PORT' to connect to server\n")
elif msg == "/q":
root.quit()
client_socket.send(b"/q")
elif msg == "/disconnect":
client_socket.close()
else:
client_socket.send(bytes(msg, "utf8"))
except:
msg_list_tk.insert(tt.END, "Wrong input\n")
A TCP socket is only usable for a single TCP connection. If you want a second connection, you need to create a new socket and call connect() on that (i.e. you can't call connect() on your old socket a second time).
I run the following script:
import socket, threading, time,Queue
if __name__ == '__main__':
pass
print("Starting...")
def server():
s = socket.socket()
host = socket.gethostname()
port = 1247
s.bind((host,port))
s.listen(5)
while True:
c, addr = s.accept()
print("Connection accepted from " + repr(addr[1]))
c.send("Server approved connection\n")
print (addr[1]) + ": " + c.recv(1026)
c.close()
def client ():
time.sleep(5)
print("Client Started")
s = socket.socket()
host = socket.gethostname()
port = 1247
s.connect((host, port))
print (s.recv(1024))
inpt = raw_input('type anything and click enter... ')
s.send(inpt)
print ("the message has been sent")
q = Queue.Queue()
t = threading.Thread(client(), args = (q))
t.daemon = True
t.start()
server()
I get this error:
Starting...
Client Started
return getattr(self._sock,name)(*args)
socket.error: [Errno 111] Connection refused
Note that port 1247 is open in my device (Ubuntu OS).
Connection Refused means there is nothing to connect to. But What is wrong with the server, I cannot find the problem with it. Any help is very much appreciated after one week of tries!
When you create the thread, you are accidentally starting the client. The first argument of threading.Thread is client(), which executes the client including the initial sleep. Which blocks the main thread. You should change this to
t = threading.Thread(target=client, args = (q,))
The target argument expects a callable object, i.e. your client. Once you start the tread, it will execute the client on a different thread. Please note, the lack of () after client.
I have written a simple script to send and receive messages using the Python socket module. I want to first send a message using sendMsg and then receive a response using listen. sendMsg works fine but when my server sends a response I receive the error:
"[WinError 10038] An operation was attempted on something that is not a socket"
I close the socket connection in sendMsg and then try to bind it in listen, but it's at this line that the error is produced. Please could someone show me what I am doing wrong!
import socket
port = 3400
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), port))
def sendMsg():
print("\nSending message:\n\n")
msg = ("Sample text").encode("utf-8")
s.send(msg)
s.close()
def listen():
s.bind(("", port))
s.listen(1)
serverSocket, info = s.accept()
print("Connection from", info, "\n")
while 1:
try:
buf = bytearray(4000)
view = memoryview(buf)
bytes = serverSocket.recv_into(view, 4000)
if bytes:
stx = view[0]
Size = view[1:3]
bSize = Size.tobytes()
nTuple = struct.unpack(">H", bSize)
nSize = nTuple[0]
message = view[0:3+nSize]
messageString = message.tobytes().decode("utf-8").strip()
messageString = messageString.replace("\x00", "")
else:
break
except socket.timeout:
print("Socket timeout.")
break
sendMsg()
listen()
Note: I have implemented listen in a separate client and used the line
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 3)
before s.bind() and s.connect(). This works OK. It would be nice to have it all in one client though.
As per the docs the socket.close() will close the socket and no further operations are allowed on it.
So in your code this line s.close() is closing the socket.
Because of that the s.bind(("", port)) will not work as the socket s is already closed!
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.