I'm making a program that needs to recieve a connection hash from a server. When I use:
connhash = s.recv(1024)
I get this error:
[Errno 10054] An existing connection was forcibly closed by the remote host
Is this my fault or the servers fault?
Here is some of the code leading up to s.recv()
stringfmt = u'%(user)s;%(host)s:%(port)d'
string = stringfmt % data
structfmt = '!bh'
encoded = string.encode('utf-16BE')
packetbytes = struct.pack(structfmt, 2, len(encoded))+encoded
s.send(packetbytes)
connhash = s.recv(1024)
I am using Python v 2.7
EDIT: This is for Minecraft just so you know.
It sounds like the remote server doesn't like your connection and cuts you off. This could mean you've made a protocol mistake (i.e., the commands you are sending are incorrect), or you may not have logged in successfully, or your IP may have been banned, or many other similar things.
To debug it, you could try using something like telnet to replicate the connection and see where the error occurs (if it doesn't, then there is something wrong with your implementation; if it does, there is something wrong with your understanding of the protocol, or you are blocked from using the server).
Alternatively, use a packet capture tool like Wireshark to look at what packets are being sent and received, and see if that shows the problem.
Related
I'm sending data via sockets between godot and python like this:
godot:
var socket = PacketPeerUDP.new()
socket.set_dest_address("127.0.0.1", 6000)
var data={...}
socket.put_packet(JSON.print(data).to_ascii())
python server:
s= socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(("127.0.0.1", 6000))
while True:
data = s.recvfrom(1024)
but the problem is even when the python server is not running the godot code sends the data instead of giving an error that the server is not available
I even tried var err=socket.set_dest_address("127.0.0.1", 6000) hopin this would print out the error
but it always prints 0 whether the python server is running or not
so how do I check if the server is available or not?
This is UDP we are talking about. So there isn't really a session or connection established. Also there isn't really an acknowledged package. So at the end the only solution is to implement your own reliability protocol on top of it (e.g. have the server respond and the client wait for the response). Try searching dor UDP reliability on the gamedev site.
The return values for set_dest_address are ERR_CANT_RESOLVE (the IP is not valid) or OK.
The returns values of put_packet. It can return ERR_BUSY (send buffers are full), FAILED (the socket is otherwise in use) or OK.
I'm trying to retrieve data from a PLC (AutomationDirect P2000). I have set up the PLC as the server with their software program (I can also connect to it with their software via Ethernet and use Wireshark to see it is in fact sending UDP packets to my machine at roughly every 200ms). I am trying to set up a very simple Python script to retrieve said data, without bothering to encode it or do anything with it, but my program hangs at the socket.recv(). Whenever I try to run it "Got here" will be printed, but "Now here" will not. From what I've read the fact that it hangs means there's no data to be received, but from my (limited) understanding of what I see on Wireshark this is not the case. I am pretty new to all of this and would appreciate any help.
I have tried using socket.recvfrom(), which produces the same result. I've also tried using socket.bind() instead of socket.connect() but I get a "The requested address is not valid in its context" exception. Additionally, I've tried playing around with various IPs and ports. For example, I've tried using IP = '' instead of the actual IP, and I've tried the source/destination information from Wireshark as what I try to bind or connect to, but nothing thus far has worked.
import socket
IP = '192.168.3.1'
PORT = 9999
BUFFER_SIZE = 4096
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect((IP, PORT))
while True:
print("Got here")
data = s.recv(BUFFER_SIZE)
print("Now here")
print(f"Received {data}")
I am expecting to get a print out of the packet in byte format, but instead the program is hanging. If I try socket.bind() instead of socket.connect() I get an error message reading "...line 8, in
s.bind((IP, PORT))
OSError: [WinError 10049] The requested address is not valid in its context"
you can't use bind like this, because the ip address does not belong to your PC.
when you connect to the server, it (the server) doesn't send anything, but you try to get data from the server, so the socket awaits until it gets data, and only then it will continue the execution (this is called a blocking function, since it blocks the execution until it finishes).
The issue was with how I set up the PLC as the server. The UDP data I was seeing on port 9999 wasn't the communications I was thinking it was, and was only the inherent communication between the PLC and the network via its proprietary program. For anyone curious, I am using a P2000 PLC from AutomationDirect and initially I set it up as an EtherNet/IP Adapter following one of their videos, but I had to use the Custom Protocol over Ethernet functionality provided in the "Communications" section.
I have a program (.exe) that gets certain info from a server, and I wanted to be able to get that info from the command line too. I started netcat and listened on the port the program uses to communicate with its target, because I wanted to know what "requests" to make from a script, and I received this over netcat, plain text:
net.tcp://[my ip address]:41012/Lapis.Btouch/ServerInfo
I tried sending exactly that to the target (replacing my IP for its IP) using socket.send() but it wouldn't return anything. What does that mean and how can I get the data?
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('[server ip address]',41012))
while True:
s.send('net.tcp://[server ip address]:41012/Lapis.Btouch/ServerInfo')
response = s.recv(1024)
print response
s.close()
That's the code I'm using to send the request to the target server. It won't return anything, so I think I'm not making the request in the right way. Thanks for any help.
Try capture your network packet on port 41012, via tcpdump or wireshark or ...
Then check:
does your code send the request?
does the response returned to you?
If the answer for question (1) is False, problem is side of you and your machine. so go and solve it (review your code, check your firewall and ...)
If the answer of question (1) is True, but server doesn't send any response (this case often not happened) review your request format (check you URL or test it via browser or ...). also based on the server you connect to, maybe needed to your machine's IP recognized for server (I mean some server only give response to requests, that come from known IP addresses, in this case you need introduce yourself to server (e.g. add your IP to trusted list on server), before sending request)
Last case, if answer of both questions are correct (I guess it's your problem), you most correct your code (response = s.recv(1024)) why do you used 1024 for your response length?. Use correct and accurate parameters.
In python exist several methods for receiving response via socket (from server), search stackoverflow and you can find useful tips and commands. commands like use non-blocking ways, ascync ways and ...
So I'm messing around with a very simple echo server/client kind of deal. I'm eventually going to be making a game server, but for now I'm just trying to setup the basic parts.
Here's the server: http://pastebin.com/qtfrMGur
Here's the client: http://pastebin.com/3VK3VxPX
So, my problem is that when the client disconnects, I get socket.error: [Errno 10054] An existing connection was forcibly closed by the remote host. I was under the impression that select.select() returned false(or an empty list, whatever) when the readable socket list had no pending information. This seems to be the cause of the error, but then why is select.select() returning true(on line 26) if the client is no longer there? The actual error occurs when I try to retrieve some info in line 27. I'm really confused by this, assuming the client-side of the socket is closed, shouldn't it just return [], and then go to the else on line 31 and destroy that client?
I don't really know what else to post, this seems like a very elementary problem, usually I use a more abstract library like twisted that makes it easy, but for this project I must use traditional BSD sockets. If you guys have any other info you need just ask.
Thanks.
EDIT: So I put a print statement in there to print the value of select.select(...)[0], like so:
for cl in clients:
ready = select.select([cl], [], [], .1)[0]
print ready
if ready:
data = cl.recv(size)
if data:
print data
#cl.send(data)
else:
print "Client Quit\n"
clients.remove(cl)
cl.shutdown(socket.SHUT_RDWR)
cl.close()
print len(clients)
As you can see I do a proper shutdown now as well. The problem is, that right as the client quits, select.select(...) returns the client socket as a readable source, so cl.recv gets called on it, which then throws an error because cl is closed on the other end. At least this is my suspicion.
So, could somebody please explain what I may be doing wrong here? Why does the client send a last dying message, is it some kind of functionality that I should be taking advantage of?
Thanks
EDIT2: So guys I fired up my debian machine and the code works flawlessly, it's only in windows that it's doing this. Is this some sort of bug? I was under the impression that the socket library abstracted all the stuff beneath the hood to make the interface identical between OS.
You should call the shutdown method of the socket, before closing it on the client side, like this:
s.shutdown(socket.SHUT_RDWR)
s.close()
That way it won't allow further sending / receiving, check out the Python docs about it, it's nicely explained there.
UPDATE: fixed client code
import socket
host = 'localhost'
port = 50000
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
msg = ''
while msg !='quit':
msg = raw_input()
s.send(msg)
#data = s.recv(size)
s.shutdown(socket.SHUT_RDWR)
s.close()
I'm working on a slightly larger project of my own and I need to make a localhost proxy in python.
The way I wrote mine is that there's a TCP server (using socket and SOCK_STREAM) on port 8080 on the localhost. It accepts a request from the local host, using slicing, string.find(), and gethostbyname() finds that target IP, so it opens up another TCP socket, sends the request and recv's a reply. After that, it relays the reply back to the localhost proxy which in turn throws it back at the browser.
This is the code with ample debugging messages and a debug file to collect the requests of the browser and the replies received back (also note this is just a prototype, hence the limited for loop instead of a while 1 loop):
import socket
local = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
f = open('test.txt', 'a')
local.bind(('localhost', 8080))
local.listen(5)
for i in xrange(20):
print '=====%d=====\n' % i
out = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
data, addr = local.accept()
print 'Connection accepted'
buffer = data.recv(4096)
print 'data recieved'
f.write('=============================================================\n')
f.write(buffer)
end = buffer.find('\n')
print buffer
#print buffer[:end]
host = buffer[:end].split()[1]
end = host[7:].find('/')
print host[7:(end+7)]
host_ip = socket.gethostbyname(host[7:(end+7)])
#print 'remote host: ' + host + ' IP: ' + host_ip
print 'sending buffer to remote host'
out.connect((host_ip, 80))
out.sendall(buffer)
print 'recieving data from remote host'
reply = out.recv(4096)
out.close()
print 'data recieved from remote host'
f.write('+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n')
f.write(reply)
f.write('\n\n\n')
print 'sending data back to local host'
data.sendall(reply)
print 'data sent'
local.close()
out.close()
f.close()
Now my problem is that it seems to work fine for the first few requests, it gets the html and a few images but at some point it always stops at the "data received" point and quits, because it gets no data ie. the buffer is empty. The browser still shows it's loading elements of the page, but when it stops and I look at the text log file, I see that the buffer was empty, meaning that the browser didn't submit anything to the proxy?
I am guessing that the issue lies somewhere in how a browser submits requests and my script not reacting properly to this behavior.
I know I could use the Twist framework, however I want to learn to write this kinda stuff myself. I've been reading about SocketServer and I might use that, but I have no clue if it'll solve the issue because frankly, I don't really understand what's causing the issue here. Is my script too slow for the browser? Do servers send more than one answer and my receiving socket should listen for more packets? Is my buffer size (4096) too small?
I'd really appreciate a nudge in the right direction.
Thanks!
Well, I managed to answer my question. What I suspected previously was partly true - the browser was waiting for something and that something was replies.
I fired up wire shark, did some experiments and I noticed that my proxy makes a lot of ugly TCP RST appear in wireshark. I also noticed that in a normal connection, a lot of the server replies are split up into a few different packets.
Basically, my program wasn't getting all the answers back from the server because the out.recv was getting just one part of the reply. The obvious answer was to make a loop and listen for all the replies. I found the perfect solution at http://www.binarytides.com/receive-full-data-with-the-recv-socket-function-in-python/ .
I quickly recoded my program a bit and it works like a charm. Now I can move on forward with my whole project.
I hope this might help anyone else in the future with a similar issue.