I'm trying to make an online FPS game and so far it works on my local network. What I'm trying to do is make it work globally
I've tried making other Python projects work globally in the past but so far I haven't been able to get it to work. I get my IP from ipchicken or whatever and put it as the HOST for the server, but when I try to start it I get this.
socket.error: [Errno 10049] The requested address is not valid in its context
I've tried many different versions of what could be my IP address found from various different places, but all of them give that output.
I thought, since I had my webspace, I could try doing what it says you can do in the Python manual:
where host is a string representing either a hostname in Internet domain notation like 'daring.cwi.nl'
So, I put in the domain of my webspace (h4rtland.p3dp.com) and I get this error:
socket.error: [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
Though only on port 80, anything else gives me the same error as before.
If anybody can shed some light on this subject for me it would be greatly appreciated.
First off, port 80 is typically http traffic. Anything under port 5000 is priviledged which means you really don't want to assign your server to this port unless you absolutely know what you are doing... Following is a simple way to set up a server socket to accept listen...
import socket
host = None #will determine your available interfaces and assign this dynamically
port = 5001 #just choose a number > 5000
for socket_information in socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM):
(family, type, prototype, name, socket_address) = socket_information
sock = socket.socket(family, type, prototype)
sock.bind(socket_address)
max_clients = 1
sock.listen(max_clients)
connection, address = sock.accept()
print 'Client has connected:', address
connection.send('Goodbye!')
connection.close()
This is a TCP connection, for an FPS game you likely want to look into using UDP such that dropped packets don't impact performance terribly... Goodluck
Related
I'll try be concise, but please let me know if I can provide any more helpful pieces of information.
I have client and server Python programs, and they work fine when ran on the same machine, and when the client connects to my machine's local IP (not 127.0.0.1, but the IP assigned to my machine). I have not been able to get this to work with my public IP.
I get a [Errno 61] Connection refused error when I try to get the client to connect to my router's public IP address. My server binds to all interfaces using bind(("0.0.0.0", 50000)), and I already set up port forwarding for my router. I verified that the program is listening on that port by running netstat -an | grep LISTEN and finding the following line:
tcp4 0 0 *.50000 *.* LISTEN
I can also seemingly reach the port through an online port checking tool, which shows that the port is open when I am running my program, and closed when I close that program. My program also registers the connection from this tool.
The fact that my program accepts the connection from the port checking tool gives me the impression that my client code is missing something, but I can't find any answers. It might be worth noting that I am still running my server and client code on the same machine, but I'm not sure why that would derail things. Here's the code I use to connect on the client side:
tcp_client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
tcp_client.connect(('my_public_ip', 50000))
Are there any diagnostic steps that I can follow to narrow down my issue?
Before you spend any more time on this, try connecting to your public ip from a computer outside your home network. Spend a couple of dollars on an AWS instance for an hour if you have to, or try connecting from a friend's machine, whatever. It will probably work just fine.
I suspect the problem is simply that you cannot, from inside your home network, connect to your router's public ip address. I tried the same thing with my local network and ran into the same behavior.
If you really need to your public ip during development, you can just assign that as an alias to one of your local interfaces (ip addr add 1.2.3.4/32 dev eth0)...but it's probably easier just to use your an address on your local network, or just arrange for regular access to a remote system for testing.
I am very new to socket programming. I am trying to connect to a power supply over ethernet. My Mac (OS X) is connected to an ethernet switch and the power supply is also connected to the switch. I have some code written in python to send/receive commands/messages to/from the power supply.
The switch interface allows me to assign a static IP to the supply. It is this same IP that I use as the target IP in the following code:
def __init__( self, IP_TARGET ):
IP = IP_TARGET
PORT = 8080
self.supply = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
self.supply.connect( (IP, PORT) )
This code runs without any issues. My next goal is communicate with the device using the following code:
def getDeviceInfo( self ):
self.supply.send('some command ')
self.supply.recv(10)
Using some print statements I have narrowed the issue down to the recv() command. The send() throws no errors. I get the following error
...in getDeviceInfo
self.supply.recv(10) socket.error: [Errno 61] Connection refused
I am able to ping the device using the IP that I assigned it using the ethernet switch. I have firewall off. I have searched the www for clues as to how I might resolve this error, but to no avail. Any thoughts?
It looks like there is nothing running on the host and port you specified (you can check it with nmap, for example).
In the case it does, is it expecting to receive anything and responding to it?
EDIT: your code is not working because in the remote host and the port you specified (8080), there must be some some code running, listening for messages and responding to them. If there is nothing running on that port, it obviously returns you the "Connection refused" error.
In other words, you created the client, but not the server :P
The port I chose was random (I thought anything above 4096 would be
okay).
See the Digi Connect® Family Command Reference on how to Access the Command Line.
The Command-Line Interface for the Digi device uses the telnet port, which is TCP port 23.
(The port number restrictions you were probably thinking of apply only if you do the server.)
I have to test a broadcast with acknowledgement on localhost. So I have some text files that represent the nodes and inside there is a list of neighbors.
I use localhost as the IP and the port is the number of the node.
The problem is when I receive a message (that I sent) from a node like 7000, python replaces it with a random number for example 65724. So now my father is 65724 instead of 7000, so I cannot remove 7000 from the list of neighbors.
I cannot complete my algorithm and that is very frustrating.
I can send a message with the port number that I want, but it's not very elegant.
Could someone tell me how to not allow python to randomize the port?
rmunn saved me, the answer I was looking far is the bind before connect method. Befor sending a message you bind your own port and you connect to the other one.
This is not a Python problem, per se. You are confused about how ports work.
Each TCP communication (sending or receiving) has two IP addresses and two ports: the host IP and host port, and the destination IP and destination port.
If you're communicating with a computer "out there" on the network, your host and destination IPs will be different. In your test case, your host and destination IPs will both be 127.0.0.1 (localhost). But I'm going to go with the "different IPs" case for my example, because it makes it easier to see.
So your IP address is, say 10.1.2.3, and you're talking to a computer at 10.1.2.99. You tell the system that you want to talk to 10.1.2.99 at port 7000, and it opens up a connection. When that happens, it will randomly pick a source port that's not in use. So now there's a two-way communication channel open:
10.1.2.3:65274 <-> 10.1.2.99:7000
Note that you did not pick that host port. EDIT: I originally said "In fact, the system will not allow you to pick the host port; it will be assigned to you" here, but that is wrong. If s is a socket object, you can call s.bind() to set its source port, then call s.connect() to connect to a destination port.
Now, when you're listening for a message, then you pick the port you're listening on, and the computer that's connecting to you will have a random port. So if you were listening for a message on port 8912, the incoming connection (once established) will look like:
10.1.2.3:8912 <-> 10.1.2.99:38290
Note that 38290 was chosen at random by the operating system of the computer at the 10.1.2.99 IP address.
Now for the bit of Python. You mention sockets in your question title, so I'll assume you're using the socket module from Python's standard library. Once you've created a socket object s, use s.getpeername() to find out the address (host and port) that you've connected to, and s.getsockname() to find out the address (host and port) that you've connected from.
Since you talk about expecting the number 7000 and getting a random number, I think you're using the host socket when you should be using the destination socket.
Server code:
import socket
import base64
filename = open("received.xvid","ab")
TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
data = conn.recv(16)
filesize = int(data)
iter = filesize//BUFFER_SIZE
i = 0
while (i < iter):
data = conn.recv(BUFFER_SIZE)
filename.write(data.decode('base64'))
if not data:
continue
i = i + 1
data = conn.recv((filesize - (iter*BUFFER_SIZE)))
filename.write(data.decode('base64'))
filename.close()
conn.close()
Client code:
import socket
import time
import base64
TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024
filename = open("test.xvid","rb")
MESSAGE = base64.b64encode(filename.read())
filesize = '%16s'%len(MESSAGE)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(filesize)
time.sleep(1)
s.send(MESSAGE)
s.close()
When I run the client code, I get "socket.error: [Errno 10061] No connection could be made because the target machine actively refused it". I don't understand why. What should I put in place of TCP_IP and TCP_PORT to make the code work?
This is what I get when I enter the command netstat -tnl.
Displays protocol statistics and current TCP/IP network connections.
NETSTAT [-a] [-b] [-e] [-f] [-n] [-o] [-p proto] [-r] [-s] [-x] [-t] [interval]
-a Displays all connections and listening ports.
-b Displays the executable involved in creating each connection or
listening port. In some cases well-known executables host
multiple independent components, and in these cases the
sequence of components involved in creating the connection
or listening port is displayed. In this case the executable
name is in [] at the bottom, on top is the component it called,
and so forth until TCP/IP was reached. Note that this option
can be time-consuming and will fail unless you have sufficient
permissions.
-e Displays Ethernet statistics. This may be combined with the -s
option.
-f Displays Fully Qualified Domain Names (FQDN) for foreign
addresses.
-n Displays addresses and port numbers in numerical form.
-o Displays the owning process ID associated with each connection.
-p proto Shows connections for the protocol specified by proto; proto
may be any of: TCP, UDP, TCPv6, or UDPv6. If used with the -s
option to display per-protocol statistics, proto may be any of:
IP, IPv6, ICMP, ICMPv6, TCP, TCPv6, UDP, or UDPv6.
-r Displays the routing table.
-s Displays per-protocol statistics. By default, statistics are
shown for IP, IPv6, ICMP, ICMPv6, TCP, TCPv6, UDP, and UDPv6;
the -p option may be used to specify a subset of the default.
-t Displays the current connection offload state.
-x Displays NetworkDirect connections, listeners, and shared
endpoints.
-y Displays the TCP connection template for all connections.
Cannot be combined with the other options.
interval Redisplays selected statistics, pausing interval seconds
between each display. Press CTRL+C to stop redisplaying
statistics. If omitted, netstat will print the current
configuration information once.
If this happens always, it means that the machine exists but that it
has no services listening on the specified port, or there is a
firewall stopping you.
If it happens occasionally and retrying succeeds, it is likely
because the server has a full 'backlog'.
When you are waiting to be accepted on a listening socket, you are placed in a backlog. This backlog is finite and quite short - values of 1, 2 or 3 are not unusual - and so the OS might be unable to queue your request for the accept to consume.
The backlog is a parameter on the listen function - all languages and platforms have basically the same API in this regard. This parameter is often configurable if you control the server, and is likely read from some settings file or the registry. Investigate how to configure your server.
Regardless of whether you can increase the server backlog, you do need retry logic in your client code to cope with this issue as even with a long backlog the server might be receiving lots of other requests on that port at that time.
There is a rare possibility where a NAT router would give this error should it's ports for mappings be exhausted. I think we can discard this possibility as too much of a long shot though, since the router has 64K simultaneous connections to the same destination address/port before exhaustion.
Also check here for more causes:
No connection could be made because the target machine actively refused it.
When I run the server and client on the same machine, things are fine. When I run them on different machines, that is when the problems arise.
OK, I know what your problem is.
TCP_IP = '127.0.0.1'
You have hardcoded this IP address into server and client. It is a special IP address that means this machine and only this machine. When you use it in bind(), the server listens for connections only from the same machine. When you use it in connect(), the client tries to connect to a server running on the same machine.
To listen for connections from any machine, as is probably your intention for the server, you call bind with the special IP address 0.0.0.0. (A complete server for production use needs to do something slightly more complicated than this, but that is enough for a test program like this one.)
To have a client connect to a server running on another machine, it needs to take the DNS name of the other machine as a command line argument, and run that through getaddrinfo to get the IP address to connect to.
You should purchase and read UNIX Network Programming, Volume 1, 3rd Edition and Advanced Programming in the UNIX Environment. They are expensive, but they are worth it. They will flesh out the above advice and teach you many other things which you need to know if you're going to write a complete network server or client. (Make sure to get the third edition of UNIX Network Programming; earlier editions contain a bunch of obsolete junk you don't need to know about. The second volume of UNIX Network Programming is also valuable but not as applicable to your current situation. Advanced Programming... is also less immediately relevant, particularly if you are on Windows, as I suspect you are from the phrasing of the error message.)
For a class project I'm trying to do some socket programming Python but running into a very basic issue. I can't create a TCP connection from my laptop to a lab machine. (Which I'm hoping to use as the "server") Without even getting into the scripts I have written, I've been simply trying interpreter line commands with no success. On the lab machine (kh4250-39.cselabs.umn.edu) I type the following into Python:
from socket import *
sock = socket()
sock.bind(('', 8353))
sock.listen(5)
sock.accept()
And then on my laptop I type:
from socket import *
sock = socket()
sock.connect(('kh4250-39.cselabs.umn.edu', 8353))
At which point both machines block and don't do anything until the client times out or I send a SIGINT. This code is pretty much exactly copied from examples I've found online and from Mark Lutz's book Programming Python (using '' for the server host name apparently uses the OS default and is fairly common). If I run both ends in my computer and use 'localhost' for the hostname it works fine, so I suspect it's some problem with the hostnames I'm using on one or both ends. I'm really not sure what could be going wrong on such a simple example. Does anyone have an idea?
A good way to confirm whether it's a firewall issue or not is to perform a telnet from the command-line to the destination host in question:
% telnet kh4250-39.cselabs.umn.edu 8353
Trying 128.101.38.44...
And then sometime later:
telnet: connect to address 128.101.38.44: Connection timed out
If it just hangs there at Trying and then eventually times out, chances are the connection to the remote host on that specific port is being blocked by a firewall. It could either be at the network layer (e.g. a real firewall or a router access-list) or at the host, such as iptables or other host-based filtering mechanisms.
Access to this lab host might only be available from within the lab or the campus network. Talk with your professor or a network administrator or someone "in the know" on the network to find out for sure.
Try to bind the server to 'kh4250-39.cselabs.umn.edu' instead of '':
sock.bind(('kh4250-39.cselabs.umn.edu', 8353))
If this does not work: Another reason could be a firewall blocking the port 8353....