Reputation: 53
I am trying to learn python sockets, but am becoming very confused by the results of the example code from the website (found here).
The only modification I have made is replacing socket.gethostname()
in the server with the local IP of my server, to allow me to run this on two computers.
When I connect, attempting to connect on port 12345 as in the example, I get this output:
Got connection from ('10.0.1.10', 37492)
This leads me to believe that it is connecting on port 37492. I would like it to connect on the port I tell it to, so I can port forward. Am I misunderstanding, or is there an extra command to specify it.
Edit: I am uploading my code:
Client.py
#!/usr/bin/python # This is client.py file
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.connect(("10.0.1.42", port))
print s.recv(1024)
s.close # Close the socket when done
Server.py
import socket
s = socket.socket() # Create a socket object
host = "10.0.1.42" # Get local machine name
port = 12345 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
c.send('Thank you for connecting')
c.close() # Close the connection
Upvotes: 4
Views: 5036
Reputation: 37093
You have reached that point in your networking life where you need to understand protocol multiplexing. Good for you.
Think of the TCP/IP stack. An application communicates with a remote application by passing application-layer data to the transport (end-to-end) layer, which passes it to the network layer (internetwork layer) which tries, without guarantees, to have packets reach the IP destination host over a sequence of hops determined by cooperating routers that dynamically update their routing tables by talking to connected routers. Each router conversation goes over a physical transport of some kind (ISDN, Ethernet, PPP - in TCP/IP the task of creating packets and transmitting the appropriate bit stream is regarded as a single "subnetwork" layer, but this is ultimately split into two when differentiation is required between the OSI physical layer (Layer 1) and the data link layer (layer 2) for protocols like DHCP.
When TCP and UDP were designed, the designers imagined that each server would listen on a specific port. This typically has the inherent limitation that the port can only handle one version of your service protocol (though protocols like HTTP take care to be backwards-compatible so that old servers/clients can generally interoperate with newer ones). There is often a service called portmapper running on port 111 that allows servers to register the port number they are running on, and clients to query the registered servers by service (program) number and protocol version. This is a part of the Sun-designed RPC protocols, intended to expand the range of listening ports beyond just those that were pre-allocated by standards. Since the preallocated ports were numbered from 1 to 1023, and since those ports typically (on a sensible operating system) require a high level of privilege, RPC also enabled non-privileged server processes as well as allowing a server to be responsive to multiple versions of network application protocols such as NFS.
However the server side works, the fact remains that there has to be some way for the network layer to decide which TCP connection (or UDP listener) to deliver a specific packet to. Similarly for the transport layer (I'll just consider TCP here since it's connection-oriented - UDP is similar, but doesn't mind losing packets). Suppose I'm a server and I get two connections from two different client processes on the same machine. The destination (IP address, port number) will be the same if the clients are using the same version of the same protocol, or if the service only listens on a single port.
The server's network layer looks at the incoming IP datagram and sees that it's addressed to a specific server port. So it hands it off to that port in the transport layer (the layer above the network layer). The server, being a popular destination, may have several connections from different different client processes on the same machine. This is where the magic of ephemeral ports appears.
When the client requests a port to use to connect to a service, the TCP layer guarantees that no other process on that machine (technically, that interface, since different interfaces have unique IP addresses, but that's a detail) will be allocated the same port number while the client process continues to use it.
So protocol multiplexing and demultiplexing relies on five pieces of information:
(sender IP, sender port, protocol, receiver IP, receiver port)
The protocol is a field in the IP header as are the source and destination IP addresses. The sending and receiving port numbers are in the transport layer segment header.
When an incoming packet arrives, the guaranteed uniqueness of different ephemeral ports from the same client (endpoint) allows the transport layer to differentiate between different connections to the same server IP address from the same client IP address and port (the worst case for demultiplexing) by their source IP address and port. The (transport) protocol is included to ensure that TCP and UDP traffic don't get mixed up. The TCP/UDP constraints on uniqueness of ephemeral ports guarantee that any server can only receive one connection from a specific combination of (IP address, port number)
and it's that that allows connections from the same machine to be demultiplexed into separate streams corresponding to the different origins.
In Python when you connect a socket to a remote endpoint the socket.accept()
call returns the (IP address, port number) pair for the remote endpoint. You can use that to discover who is communicating with you, but if you just want to talk back you can simply write()
the socket.
Upvotes: 6
Reputation: 81
The message that appears comes from the server. It just gives you information that connection was established from the client's port 37492.
This is what happens:
Your server (server.py) is listening on port 12345. Your client (client.py) connects to the port 12345 of the server. The TCP connection is always established between two ports - source and destination.
So, looking from your client app perspective 12345 is the destination port and 37492 is the source port. In other words client establishes a connection from its local port 37492 to the remote servers port 12345.
If you want to set up port forwarding you may still do it as the port on which server listens is well known (12345) and the source port of the client doesn't really matter in this situation.
Upvotes: 1
Reputation:
The port that you get in your output is the source port. Your client program sends to the server on the port you choose (in this case, 12345), but it also needs a port to receive data sent by the server, so it randomly chooses a source port and tells it to the server.
I suggest you read some more about TCP and ports in general.
Upvotes: 0
Reputation: 13779
The key word is "from." That's the port that the client is connecting from, 12345 is the one your server is listening on and the client is connecting to.
Upvotes: 1