What is `conn, addr = s.accept()` in python socket? - python

I searched documentations and tutorials but no one talked about this, for example this is server script
import socket
server = socket.socket()
print("socket created")
server.bind(("localhost", 9999))
server.listen(3)
print("waiting for connection")
while True:
client, addr = server.accept()
print(client)
print(addr)
name = client.recv(1024).decode()
print("connected with", addr, client, name)
client.send(b"welcome bro")
client.close()
When printing client, I get this:
proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 36182)
And addr variable :
('127.0.0.1', 36182)
Why these two variable defined by one and got two different output?
What is the logic behind scene?

From the documentation of the socked module:
socket.accept()
Accept a connection. The socket must be bound to an
address and listening for connections. The return value is a pair
(conn, address) where conn is a new socket object usable to send and
receive data on the connection, and address is the address bound to
the socket on the other end of the connection.

The script does not answer this by itself, however, I assume laddr=('127.0.0.1', 9999) is the listening address of the server-side app. That's where connections are established. the raddr is the connection port the request comes from. When you listen to a port with a server, the client uses any non-reserved port >1024 to connect to the server and this is totally random, as long as it is defined in the client-app.
So you have to different connection points for one established connection. The one port and address as the sender-side (described as raddr) and the one as the receiver side (here described as laddr - for listen)
That's basically the logic behind any TCP-related connection.

accept() function returns a socket descriptor that is connected to your TCP server. In this case, it returns a tuple of objects.
The first parameter, conn, is a socket object that you can use to send data to and receive data from the client that is connected.
The second parameter, addr, contains address information about the client that is connected(e.g., IP address and remote part).

Related

Python, TCP sendall

How can I send to a specific client? TCP Server can send to all clients
I store the sendip and sendport, obtained using this code:
clientssendback = []
clientsocket, address = s.accept()
clientssendback.append(address)
for x in clientssendback:
sendip = str(x[0])
sendport = str(x[1])
clientsocket.sendall(bytes("hello", "utf-8"), (sendip, sendport))
I'll have so I can send it to all client there are loged into the server.
Can some one help me with that? Am I doing the right thing?
i have a few notes:
the accept() function returns a tuple. the first is the connection made between the server and client. it is not the client's socket.
this means that you establish a unique connection between every client and the server when you accept him. the transfering of data happens through this coonection.
first you need to save these coonections in a list, and loop between them, and send the message to each client
import socket
connections = []
server_socket = socket.socket() # by default it's TCP/IP
server_socket.bind((ip_address, port)
server_socket.listen(20)
conn, addr = server_socket.accept()
connections.append(conn)
now you now how to establish a connection and save it in a list. now lets send a message which is "hello" to all clients
for connection in connections:
connection.send(b"hello") # the b changes the string to bytes

Only one usage of each socket address (protocol/network address/port) is normally permitted,

I have a server that uses a thread to listen for new connections and then starts one thread for every client to serve him. Now, the server runs perfectly, but when a client connects it gives me the error in the title. I think because both client and server are trying to use the same port.
Here's the server code:
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
def __init__(self, conne):
initialization
def handle(self):# "run"
does something
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
HOST = '' # Symbolic name meaning all available interfaces
PORT = 1000 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
n=1
while 1:
conn, addr = s.accept() # wait for a new connection. Get a new socket (conn) for each new connection
print 'Connected by', addr
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler) #this line gives me the error
ip, port = server.server_address
server_thread = threading.Thread(target=server.serve_forever)
server_thread.setDaemon(True)
server_thread.setName('Client '+str(n))
server_thread.start() # Start the new thread
n+=1
server.shutdown()
server.server_close()
And here's the client:
import socket
HOST, PORT = "localhost", 1000
data = "0"
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
sock.sendall(data)
received = sock.recv(1024)
finally:
sock.close()
print "Sent: {}".format(data)
print "Received: {}".format(received)
First you create server socket and bind it to port 1000. Then when client connects you receive a socket connected with client (conn, addr = s.accept()) that should be used to communicate with client but you completely ignore it. Instead you create another server that tried to bind again to port 1000. This results in "already used" error as expected.
I'd suggest you check this example of TcpServer threading and forking. Here a custom class derived from SocketServer.TCPServer is created initially (not a simple server socket as you do). It internally loops over accepting incoming client connections and for each connection calls specified SocketServer.BaseRequestHandler from a new thread or process (in case of forking) so you don't need to deal with them explicitly. Custom request handler just needs to, well, handle the request, potentially in a loop if communication with client is multi-step.
Be aware that thread/process per client approach doesn't scale well on large number of simultaneous client connections.

Python Socket, how do i choose between s.send and conn.send?

def send_Button():
try:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
except NameError:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
This program uses the tkinter module with socket in python2.7. My program allows for you to either connect to a server to chat with or host a server for others to connect to you, but whenever I try and test it out then the lines with the '###' on always bring up an error and it doesn't work, the error which comes up is: "NameError: global name 'conn' is not defined" OR "error: [Errno 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied".
Any help please?
I think that you are trying to get the program to act as a Client or as a Server just changing s.send() to conn.send() saddly it isn't that simple.
Socket Initializzation
The socket have to be initialized before sending or receiving data.
For a client usually it's something like this.
send_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
send_socket.connect((serverIp, serverPort)) # Connect to the server
send_socket.send(data) # Send the data to the server
And like this for a Server:
listen_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
listen_socket.bind(("0.0.0.0", port)) # Set the socket to accept client from every interface on the port port
listen_socket.listen(1) # Put the server on listen on the port setted before
accept_socket, addr = self.listen_socket.accept() # when a client connect return the socket to talk with it
data = self.accept_socket.recv(buffer_size) # Receive data form the client of max size buffer_size
Docs examples
From your question I guess that with s.send() and conn.send() you are talking about
this example from the python 2.7 socket docs
Here are four minimal example programs using the TCP/IP protocol: a server that echoes all data that it receives back (servicing only one client), and a client using it. Note that a server must perform the sequence socket(), bind(), listen(), accept() (possibly repeating the accept() to service more than one client), while a client only needs the sequence socket(), connect(). Also note that the server does not sendall()/recv() on the socket it is listening on but on the new socket returned by accept().
Client
Echo client program
import socket
HOST = 'daring.cwi.nl' # The remote host
PORT = 50007 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)
the client is pretty stright forward, it create the socket s and then after using s.connect() it just send data through it.
Server
The server one is where there there are both s and conn
Echo server program
import socket
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
conn.close()
in this one first of all we create a socket s on which the server will listen and then using s.accept() it will wait till a client connect to the server and then return the conn which is the socket of the connected client.
So to receive or send data to the client you have to use conn.
Notes
As said in the documentation in these two example the server accept only one client. So if you want to deal with multiple clients you have to repeat the accept step and possibly generate a new Thread for each client so that other clients don't have to wait for each others.

Python connected datagram socket

I'm building a simple client-server multiplayer game and I want to have connected UDP sockets. However, when I call the listen() method it produces Operation not supported exception.
try:
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind((host, port))
server.listen(5)
except socket.error, (value, message):
print "E: " + message # E: Operation not supported
Is there a way to have connected datagram sockets?
UDP protocol is connectionless and thus you really cannot create connections between 2 sockets in the same manner as with the TCP client and server; thus you also cannot do the listen system call on an UDP socket, as it concerns only the TCP server sockets. Instead you use socket.recvfrom to receive datagrams from any address:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((host, port))
data, addr = sock.recvfrom(65536) # this will fit the maximum datagram
You can respond to the client (if they still have a socket open), by destructuring the addr which is a host, port tuple for socket.AF_INET, socket.SOCK_DGRAM.
client_host, client_port = addr
You can send data back there with sendto
sock.sendto(data, (client_host, client_port))
If you want to use a well-known port, you will bind the socket; if not, the system will assign a port for you.
It is possible to do a connect system call with datagram sockets on many socket implementations; this serves as a sort of filter, that drops the packets coming from unwanted sources, and for setting the default outgoing address for sock.send (it is still OK to use sock.sendto on such socket to another address, though the response might be dropped because of the "connection"). This is very useable on a client or between 2 nodes if they agree to use 2 well known ports with each other.
However if you do connect on server, it cannot serve any other requests on this socket. Also, listen with its queues only relates to SOCK_STREAM sockets.
Thus in case of many clients to 1 server, you could have the server listen to socket 12345, and when a client contacts the server, the server could respond from server:12345 with a message that contains another port number that the client should use with the server.

Server send data in python

I'm writing a simple client server app in python, where the client is listening every type of data entering in the specific port, and I want to when receiving a data flow, send back to the connected client (which have a dinamic ip) a string, in this case "001". But when I try to send the message, it fails!
#!/usr/bin/env python
import socket
TCP_IP = '192.168.1.115'
TCP_PORT = 55001
BUFFER_SIZE = 1024
MESSAGE = '01'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print ('Connection address:', addr)
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print ('received data:', data)
conn.send(data) # echo
print ('Sending data to client...')
addr change every connection .. i cannot manage this!
s.connect((addr, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
(Connected stream) sockets are bidirectional, so there's no need to call connect to get a connection to the client—you already have one.
But you want to know why your code fails. And there are at least three problems with it.
First, after you call listen or connect on a socket, you can't call connect again; you will get an exception (EISCONN on POSIX, something equivalent on Windows). You will have to create a new socket.
Second, is client actually binded and listening for a connection on the same port as the server? If not, your connect can't work. If so, the bind will fail if the client and server are on the same machine.
Third, the addr you get back from accept is a (host, port) pair, not just a host. So, as written, you're trying to connect((('192.168.1.115', 12345), 55001)), which obviously isn't going to work.
You are trying to reply to the client using the server listening socket (s). This is only possible in UDP Servers. Since this is a TCP Server you have to use the conn which is crated using s.accept() to communication with remote client.

Categories