Now here is sample for the server part of socket.
I want to have serverSocket and connectionSocket with different port number, but for now, they are using same port number.
from socket import *
serverPort = 12000
serverSocket = socket(AF_INET,SOCK_STREAM)
serverSocket.bind((‘’,serverPort))
serverSocket.listen(1)
print (‘The server is ready to receive’)
while 1:
connectionSocket, addr = serverSocket.accept()
sentence = connectionSocket.recv(1024)
capitalizedSentence = sentence.upper()
connectionSocket.send(capitalizedSentence)
connectionSocket.close()
if they are using same port number, would there be some collision?
There is nothing to avoid, and there is really no easy way to avoid it - this is how TCP is supposed to work.
In TCP there are 2 kinds of sockets:
listening server sockets
connected sockets
The server sockets start listening to incoming connections with listen; and wait for client connections with accept. Clients create a socket that is connected to the server address (host, port). When the server accepts a connection, a new connected socket is created between the (client_address, client_port) and (server_address, server_port). The TCP stack on the server can see from status bits easily if the packet is a connection request, or destined to an already connected socket. If it is a communication between already connected sockets, then it finds out the file descriptor that is bound on the local address and local port and is connected with the source address, source port of the remote end.
The connected socket will have the same port as the listening server socket; both Ende of the socket know 4 things: local address, local port, remote address and remote port. You can have 1 server socket bound on 10.20.30.40:12345 at the same time with thousands of sockets connected from 10.20.30.40:12345 to thousands distinct addresses.
There is really congestion only in the connection attempt phase; the server_socket.listen(1) means that the server will queue just 1 incoming connection; subsequent connections will be rejected until the incoming connection is accepted.
From Linux manual pages, listen(2) on the backlog argument of sock.listen:
The backlog argument defines the maximum length to which the
queue of pending connections for sockfd may grow. If a connection request arrives when the queue is full, the client may
receive an error with an indication of ECONNREFUSED or, if the
underlying protocol supports retransmission, the request may be
ignored so that a later reattempt at connection succeeds.
Althouh I've never used raw sockets in Python, I guess this question more generally deals with how TCP and IP work.
When a server listens for connections on a port, clients will connect to that port, and the TCP connection can be identified by the quadruple (server_addr, server_port, client_addr, client_port), so there is no ambiguity when packets belonging to different connections will be sent or recieved, because the (client_addr, client_port) part will be different for each of them.
That said, there is no conflict in the addressing.
However, note that it is common that servers fork (or spawn a thread) after accepting each request, so that the main proces (or thread) can keep acceprint connections while other connections are handled by the forked processes (or threads). In your case, instead, once your server starts processing a request, it computes the response before calling accept() again, so any other client will have to wait before having its request served.
Related
I'm relatively new to Python, so apologies for what me a simple question, I just cannot find the solution. First off, I am not looking for the client's hostname. My situation is that I have a simple socket server (basically this https://docs.python.org/3/library/socketserver.html#socketserver-tcpserver-example) which clients connect to. The exact server code is;
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
"""
The request handler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 8080
# Create the server, binding to localhost on port 9999
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
The clients connect successfully and are sending data which the server is receiving. My issue is that need to know the hostname that the client used to connect. The architecture will be like;
client1 will connect to client1.mydomain.net:8080
client2 will connect to client2.mydomain.net:8080
client3 will connect to client3.mydomain.net:8080
The DNS entry for client1.mydomain.net, client2.mydomain.net and client3.mydomain.net will all map to 123.123.123.123 so behind the scenes there is only one server.
The 3 clients will connect to their respective server and send their data. I have no control over the payload and I cannot augment it with a string or parm like "client=1".
So my question is, is there a way in python sockets (on the server) to know the hostname that a client connected to, so for example I know when I'm process data from client1.
Thanks!
Nothing at the TCP level reveals which hostname the client is connected to. This means there is no way for a generic TCP server to get this information.
Various protocols on top of TCP contains such information though. For example HTTP has a Host header so that different domains with different contents can be server on the same IP and port. TLS has the server_name extension in the TLS handshake so that the expected certificate can be given matching the hostname used by the client.
Thus, if you need this information you need to define your application protocol so that the client will include this information.
First of all I am not talking about a tcp or udp or socket implemented in a vps or server
My question is just like client to client socket communication.
Imagine listening at your home pc with a tcp socket. You can connect to this from home inter network anyway. But suppose someone wants to connect to it via the internet. Then you can create a forwarding rule on the router and bring it to working condition. Then the router knows that if an incoming connection comes from a port, the connection will be forwarded to the device in the relevant inter network.
But the ISP I use does not support port forwarding.
I thought these were not impossible because of the team-viewer software. Because when I was connected to a friend in team-viewer, I opened the wire-shark and reviewed it.
Then I saw that the data packet is exchanged peer to peer. Because the destination source addresses were my ip and friend's ip
This means that the video data is exchanged without the participation of an additional server
I highlighted the team-viewer connection.
61.245.175.81 is my friend's public IP. 192.168.1.130 is my internal IP
I want to do the same
Here is my simple socket code. This does not work through the internet because there is no router forwarding rule. I am very new to socket and networking side
Sever
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('', 12000))
while True:
message, address = server_socket.recvfrom(1024)
message = repr(message)
print("Connected from -> " + str(address) )
print("Received data -> " + message)
reply = b"Hi from server :) "
server_socket.sendto(reply, address)
Client
import time , datetime
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.settimeout(1.0)
message = bytes(str(datetime.datetime.now()),'utf-8')
addr = ("192.168.1.130", 12000)
client_socket.sendto(message, addr)
try:
data, server = client_socket.recvfrom(1024)
print( repr(data) )
except: #socket.timeout:
print('REQUEST TIMED OUT')
Can anyone give an explanation for my question
Pretty sure they do it using UDP hole punching, you'd need to do something similar to implement this.
In a nutshell two clients behind NAT (which is what your router is doing) can use a third server acting as a sort of mediator to establish a connection.
I'm trying to run the below program but I keep getting connection error's:
from socket import *
from codecs import decode
HOST = 'localhost'
PORT = 5000
BUFSIZE = 1024
ADDRESS = (HOST, PORT)
server = socket(AF_INET, SOCK_STREAM)
server.connect(ADDRESS)
dayAndTime = decode(server.recv(BUFSIZE), 'ascii')
print(dayAndTime)
server.close()
ERROR: ConnectionRefusedError: [Errno 61] Connection refused
Any idea what's going on?
If your book doesn't mention the other half of sockets, you need a better book.
Socket basics are easy. You have one process listen on a port, waiting for connections. Commonly we'll call this a 'server'. Another process (perhaps on the same machine, perhaps remote) attempts to connect to that port. We'll call that the client.
If no one is listening, then when the client attempts to connect they'll get your error Connection Refused.
So, set up a listening process. Below, on the left is server code; on the right is client code. Top-to-bottom is the "flow".
server = socket(AF_INET, SOCK_STREAM) # <- just like your example
server.bind(ADDRESS) # rather than 'connect', we 'bind' to the port
server.listen(1) # bind "claims" the port, so next we call listen & wait...
# Meanwhile...
# Your client process
client = socket(AF_INET, SOCK_STREAM)
client.connect(ADDRESS)
# It's only at this moment that the client reaches across the network to the server...
# On connect, the listening server wakes up, and needs to "accept" the connection
(s, remote_addr) = server.accept()
Once accepted, you can now send/recv on the s socket on the server-side, and send/recv from the client socket on the client side. Note that the server variable is not the socket to communicate on -- it's used to listen for new connections. Instead, you read/write on the socket object returned as first item of accept().
There's lots more to consider but this is at the heart of the Internet and has been pretty much unchanged since the 1980s.
Image from wikipedia entry for Berkeley Sockets:
I want to select a random high port on a remote linux machine and use it for my application. On my localhost, I can bind to port 0 and get a random high port, but this does not work if I give a remote host.
The code is as follows:
host = "remote_host"
def get_open_port():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,0))
s.listen(1)
port = s.getsockname()[1]
s.close()
return port
Error:
Traceback (most recent call last):
File "server.py", line 25, in <module>
port = get_open_port()
File "server.py", line 11, in get_open_port
s.bind((host,0))
File "<string>", line 1, in bind
Well I guess you are bit confused with the client-server communication. Before getting to the solution of your problem lets first revisit the client-server communication process. Normally it is the client who makes/initiates the connection request (simply a connection) to the server. The client makes a request to the server on a remote port which is listening for incoming connections. This remote port should be open on the server side and should be waiting for incoming connections. For eg: If you want to connect to a remote server on the remote port number 15200, then it is mandatory that you should open the port number 15200 on the server side and it should be listening for any incoming connections/requests. Also, the client will know this in advance to which remote port it should make a request for a connection!
Lets understand some more facts before getting to the one of the possible solution to your problem. First lets understand the server side.
Server side: You are trying the server to use any random port for accepting incoming connections from a client. It will surely work as you are binding port number 0 in your server code as s.bind((host,0)). When you bind the port number 0 then your server (actually the OS which is running the server script) will use any random high port number for accepting the remote connections which will be usually greater than 1023. You can test this by following code snippet. Run the following code snippet and you may notice that the server is opening random high port numbers.
import socket
host = "127.0.0.1"
def get_open_port():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host,0))
s.listen(1)
port = s.getsockname()[1]
s.close()
return port
for i in range(0,5):
print "Opening port no. %s"%get_open_port()
On executing the above code you'll shall see that a random port number is being selected by the server code to accept incoming connections every time. But it is also closing it after wards using s.close(). In my case the output was as below (You may get a different set of port numbers):
Opening port no. 60876
Opening port no. 60877
Opening port no. 60878
Opening port no. 60879
Opening port no. 60880
So, I guess now you understood the server part. Lets discuss the client side now.
Client side: As mentioned earlier that a client needs to know the remote server port to which it needs to connect. A typical client code looks as given below:
import socket
host = "127.0.0.1"
port = 60880
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
In the above code snippet this line s.connect((host, port)) you need to mention the host the remote host name or IP and port the remote port to which you want to connect to.
So it means that client should know the port number in advance! As a result you have to mention the port in your client code. As I have done in my code snippet as port = 60880.
Now coming to your question: As you already noticed from above text that you have to mention the remote server's port number in client code to make a request for a connection. So, you can't expect your client to figure out itself the remote port of the server which is actually listening for incoming request. The client code can't do this by its own.
Solution:
So what if the client code can't figure out by itself the remote port number we'll make it to figure it out! ;) What we know is if you bind the port number 0 on server side then a random port number will be selected which will be greater than 1023. So, it means the random port number will always be greater than 1023. Also, the maximum value of port number is 65535. Ultimately we come to a conclusion that the random port that will used by the server will be any port number in this range 1024 - 65335.
Now all you have to do is in your client code you have to use a range of port numbers to which it should make connection. Because we don't know what remote port is listening on the server side for accepting incoming requests/connection!
Sample code for plying around: I tested these code snippets using my localhost. Here is the server code. Run the server code first then run the client code. Upon executing the server code, it'll display in console/output that what is the random port number opened for accepting incoming request/connections. When a client is connected the server will display a message the Got a client connected along with the IP of the client.
#This is the server script
import socket
host = "127.0.0.1"
def get_open_port():
mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mySocket.bind((host,0))
mySocket.listen(1)
port = mySocket.getsockname()[1]
print "Port opened for incoming connections %d"%port
(clientSocket, clientAddress) = mySocket.accept()
print "Got a client: ", clientAddress
clientSocket.close()
mySocket.close()
get_open_port()
Here is a client code sample that will do this crazy stuff. It will try to connect on all the ports from 1024 - 65335 and when it finds any remote port which is listening for incoming connections. It will display a message "Connected to remote port" and then close the socket and continue looking for more open ports until it reaches the last port number 65355.
#This is the client script
import socket
host = "127.0.0.1"
def startConn():
for port in range(1024,65336):
try:
myClientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Trying remote port: ",port
myClientSocket.connect((host,port))
print "Connected to remote port: ",port
myClientSocket.close()
except socket.error as msg:
myClientSocket.close()
continue
startConn()
This is just a sample code, I am intentionally closing the sockets after a successful is established. You can do something else what you ever you prefer. I hope now it is quite clear to you regarding server-client communication.
If a TCP socket is defined by a 4-tuple (source IP,source port,destination IP,destination port), then what would be the values for a TCP socket created in Python after the following Python code has been executed (i.e. when a server application is set to 'listen' to this socket)?
from socket import *
serverPort = 12000
serverSocket = socket(AF_INET,SOCK_STREAM)
serverSocket.bind((‘’,serverPort))
serverSocket.listen(1)
print ‘The server is ready to receive’
In particular, what does Python set for the destination values of a socket that a server is listening to?
Are these values randomly set, and if so how can I view them once a socket has been created?
The above code and question is taken from, and relates to, Kurose-Ross-Computer Networking.
Thanks in advance.
To query the source and destination addresses of a socket, call the getsockname() and getpeername() methods on the socket object.
In your case, serverSocket.getsockname() returns ('0.0.0.0', 12000) because that is the bind address you specified. getpeername() on a server socket always raises a socket.error: Transport endpoint is not connected because the server socket cannot be connected to a remote peer.
For a server socket to accept incoming connections, you must call its accept() method. This will return a client socket for which the peer name will be the pair of (address, port), address being the IP address of the peer, and port being the local port number assigned for communication with the peer.
If a TCP socket is defined by a 4-tuple (source IP,source port,destination IP,destination port)
It isn't. A TCP connection is so defined. A TCP socket is just an endpoint.
then what would be the values for a TCP socket created in Python after the following Python code has been executed (i.e. when a server application is set to 'listen' to this socket)?
It would have a local port of serverPort, a local address of 0.0.0.0, and no remote address or port.