Socket uses random ports and I need a certain one - python

Here is the problem, I want to create a connection between two computer in two networks in a certain port but when I am running the run I got this message that shows me every single time different ports:
Accepted a connection request from 192.168.1.2:**12345**
DATA
This is the listening code:
import socket
import logging
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverSocket.bind(("**server's Local ip**",6464))
serverSocket.listen(1)
while(True):
(clientConnected, clientAddress) = serverSocket.accept()
print("Accepted a connection request from %s:%s"%(clientAddress[0], clientAddress[1])) #[0], ...[1]
dataFromClient = clientConnected.recv(1024)
print(dataFromClient.decode())
clientConnected.send("Hello User".encode())
user = dataFromClient
cip = clientAddress
LOG_FILENAME = '/home/user/listenlog.txt'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG)
logging.debug(cip)
logging.debug(user)
logging.debug("--------------------------------------------------------")
and this is the client code:
import socket
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSocket.connect(("**Server's IP**",6464))
data = 'Hello'
clientSocket.send(data.encode())
dataFromServer = clientSocket.recv(1024)
print(dataFromServer.decode())
How should I make the using port static?

if the connection that you got is public and behind nat
it is usual to be a random port because it is from isp or nat device so else i dont think that would be local

If you want your client’s socket to be bound to a specific port, you can call bind() on the socket before you call connect() on it.
Note that there is typically no benefit to doing that, however. The downside is that if that port is already in use, the bind() call will fail.

Related

TypeError when using AF_INET in the sockets library

I am using the socket library for Python. I'm trying to make a local server. The server runs correctly, but the client does not. When I say that I want to connect to AF_INET it gives me a TypeError. It says that the AF_INET address must be a tuple, when it is a string.
Here is my code:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(socket.gethostname())
print("client successfully started")
msg = s.recv(1024)
print(msg.decode("utf-8"))
I am using version 3.10.0 (of python), if that helps.
From the socket documentation:
A pair (host, port) is used for the AF_INET address family, where host is a string representing either a hostname in internet
domain notation like 'daring.cwi.nl' or an IPv4 address like
'100.50.200.5', and port is an integer.
For IPv4 addresses, two special forms are accepted instead of a host address: '' represents INADDR_ANY, which is used to bind to
all interfaces, and the string '<broadcast>' represents
INADDR_BROADCAST. This behavior is not compatible with IPv6,
therefore, you may want to avoid these if you intend to support IPv6
with your Python programs.
For a local server, you can just use 'localhost' for the client.
Example:
from socket import *
PORT = 5000
# for server
s = socket() # AF_INET and SOCK_STREAM are the default
s.bind(('',PORT)) # must be a 2-tuple (note the parentheses)
s.listen()
c,a = s.accept()
# for client
s = socket()
s.connect(('localhost',PORT))
The connect function takes in a tuple, so you need an extra set of parentheses. It's not clear what you are trying to do with gethostname. Also, you need to have a port number to connect to. If you are trying to listen to localhost, the code would look like this:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Add socket.gethostbyname and add port number
s.connect((socket.gethostbyname(socket.gethostname()), 8089)) # Add another set of parentheses as you need a tuple
print("client successfully started")
msg = s.recv(1024)
print(msg.decode("utf-8"))
Even this may result in a ConnectionRefusedError: [Errno 61] Connection refused error, because you might have to to use the IP address from the server. Something like: 192.168.0.1. To get your IP address, do ipconfig in your cmd prompt (on Windows).
So the correct code would look like this:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect('192.168.0.1', 8089)) # Your IP instead of 192.168.0.1
print("client successfully started")
msg = s.recv(1024)
print(msg.decode("utf-8"))
I found the answer!
here is the code for everyone that has the same problem as me
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(),3000)) #you can use another port if you want
s.listen(5)
print("server successfully started")
while True:
clientsocket, address = s.accept()
print(f"connection has been established from {address}")
clientsocket.send(bytes("Welcome to the chatroom!", "utf-8")) #this sends message to the client in utf-8

A request to send or receive data was disallowed because the socket is not connected in Python

I'm trying to make a console chat app in python using socket library.
Whenever I send a message to the server, the server code crashes with the following message:
OSError: [WinError 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
Server code
import socket
HOST = socket.gethostbyname(socket.gethostname()) # get the ip address of PC
PORT = 5050
ADDRESS = (HOST, PORT)
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind(ADDRESS)
while True:
socket.listen()
conn, addr = socket.accept()
print(f"Connected by {addr}")
while True:
data = conn.recv(64)
print(data.decode('utf-8'))
socket.send(data)
Client code
import socket
HOST = socket.gethostbyname(socket.gethostname()) # get the ip address of PC
PORT = 5050
ADDRESS = (HOST, PORT)
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect(ADDRESS)
while True:
msg = input("Enter your message")
socket.send(msg.encode('utf-8'))
data = socket.recv(64)
print(data.decode('utf-8'))
What I am trying to achieve is whenever I send a message to the server, the client script should print the sent message. How can I fix that?
You're attempting to send data to your own server socket. You instead want to send to the client that you accepted.
socket.send(data)
Should be:
conn.send(data)
If you think about it, if you had multiple clients, how would you send data to a specific client? By using the socket that accept gave you.
As a side note, you probably don't want to import the module as socket, and also call your variable socket. It's fine here, but if you were to make a more complicated project, you may accidentally refer to the object when you meant to refer to the module. I'd rename the socket object to sock or server_socket to avoid shadowing.

How to make a TCP server handle multiple clients?

I'm trying to make a Python server where multiple clients can connect but I've run into a problem I tried everything that I found on the internet.
I'm running a laptop whit windows 7 and an I3 processor.
This is the file called tcp:
import socket
def make_server (ip,port):
try:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((ip, port))
server.listen(1)
return server
except Exception as ex:
print(ex)
return None
def accept(server):
conn, addr = server.accept()
return conn
def make_client():
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
return client
def client_connect(client,ip,port):
client.connect((ip,port))
def sendall(conn,mess):
conn.send(str(mess).encode("utf-8"))
def rec(conn,rate):
mess = conn.recv(rate).decode("utf-8")
return mess
def close(client):
client.close()
This is the server:
from multiprocessing import Process
from random import randint
import tcp
import sys
def start(sip, sport):
print("Making sob server...")
print("id= {}".format(sport))
sserver = tcp.make_server(sip, sport)
print("Sub Server Started!")
sconn = tcp.accept(sserver)
tcp.sendall(sconn, "connected!!")
while True:
try:
tcp.sendall(sconn, randint(0, 100))
except Exception as ex:
print("")
print("From server {} error:".format(port))
print(ex)
print("")
break
ip = "192.168.0.102"
port = 8000
subport = 9000
server = tcp.make_server(ip, port)
if server is None:
sys.exit(0)
print("Started!")
while True:
print("Wating for new connection!")
con = tcp.accept(server)
print("Connected!")
subport = subport + 1
tcp.sendall(con, subport)
print("New Port Sent!")
print("New Port = {}".format(subport))
subs = Process(target=start, args=(ip, subport))
subs.start()
subs.join()
This is the client:
import tcp
import time
nport = 0
ip = "192.168.0.102"
port = 8000
client = tcp.make_client()
tcp.client_connect(client,ip,port)
nport = tcp.rec(client,1024)
print(nport)
tcp.close(client)
nport = int(nport)
time.sleep(1)
print(nport)
client = tcp.make_client()
tcp.client_connect(client,ip,nport)
while True:
mess = tcp.rec(client, 1024)
if(mess):
print(mess)
The error is:
[WinError 10048]Only one usage of each socket address (protocol/network address/port) is normally permitted Python
Feel free to change anything you want.
If you need any info in plus just ask.
You are creating a socket in the client with tcp.make_client. You are then using that socket to connect to the server via tcp.client_connect. Presumably you successfully receive the new port number back from the server. But then you are trying to re-use the same socket to connect to those ports.
This is the proximate cause of your error: A socket can only be used for a single TCP connection. If you want to create a new connection, you must first create a new socket.
That being said, if you are simply trying to create a server that will accept multiple connections, you're making it way too complicated. The server can receive any number of connections on its single listening port, as long as a different address/port combination is used by each client.
One way to structure this in a server is something like this:
# Create and bind listening socket
lsock = socket.socket()
lsock.bind(('', port))
lsock.listen(1)
while True:
csock, addr = lsock.accept()
print("Got connection from {}".format(addr))
# Start sub-process passing it the newly accepted socket as argument
subs = Process(target=start, args=(csock, ))
subs.start()
# Close our handle to the new socket (it will remain open in the
# sub-process which will use it to talk to the client)
csock.close()
# NOTE: do not call subs.join here unless you want the parent to *block*
# waiting for the sub-process to finish (and if so, what is the point in
# creating a sub-process?)
There are several others ways to do it as well: you can create multiple threads to handle multiple connections, or you can handle all connections in a single thread by using select or with asynchronous I/O.
The client is typically much simpler -- as it usually only cares about its own one connection -- and doesn't care which way the server is implemented:
sock = socket.socket()
sock.connect((ip, port))
while True:
sock.send(...)
sock.recv(...)
If the client does wish to connect to the same server again, it simply creates a second socket and call its connect method with the same server IP and port.
Usually, the client never needs to specify its own port, only the server's port. It simply calls connect and the client-side operating system chooses an unused port for it. So the first time, the client creates a socket and connects it (to the server's listening port), the client-side OS may choose port 50001. The next time it creates and connects a socket, it may get 50002 and so on. (The exact port numbers chosen depend on the operating system implementation and other factors, such as what other programs are running and creating connections.)
So, given client IP 192.168.0.101 and server IP 192.168.0.102, and assuming the server is listening on port 8000, this would result in these two connections:
(192.168.0.101/50001) ====> (192.168.0.102/8000)
(192.168.0.101/50002) ====> (192.168.0.102/8000)

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: Socket.error Connection Refused in Unix [Errno 111]

I am trying to send UDP video packets using sockets in Python.
The Server IP address is :192.168.67.14
The Client IP address is 192.168.67.42
The Client and Server can ping each other. Below is the code used for establishing the socket:
Server Side:
import urllib, time, os, m3u8
from socket import *
# Socket initialization
s = socket(AF_INET, SOCK_DGRAM)
host = "192.168.67.42"
port = 5000
buf = 1024
addr = (host, port)
s.connect((host, port))
ts_filenames = []
while True:
playlist = "https://sevenwestmedia01-i.akamaihd.net/hls/live/224853/TEST1/master_lowl.m3u8"
m3u8_obj = m3u8.load(playlist)
ts_segments = m3u8_obj.__dict__.values()[6]
ts_segments_str = str(m3u8_obj.segments)
for line in ts_segments_str.splitlines():
if "https://" in line:
ts_id = line[-20:]
if ts_id not in ts_filenames:
print ts_id
ts_filenames.append(ts_id)
try:
ts_segment = urllib.URLopener()
ts_segment.retrieve(line, ts_id)
except:
pass
f = open(ts_id, "rb")
data = f.read(buf)
while (data):
if (s.sendto(data, addr)):
print "sending ..."
data = f.read(buf)
Client Side
import socket
s = socket.socket()
host = '192.168.67.14'
port = 5000
s.connect((host,port))
print s.recv(1024)
s.close
Exception I get:
Traceback (most recent call last): File "client.py", line 7, in
s.connect((host,port)) File "/usr/lib/python2.7/socket.py", line 228, in meth
return getattr(self._sock,name)(*args) socket.error: [Errno 111] Connection refused
I spent some time looking into this discussion but I still not sure what to modify. Any suggestions please ?
You have multiple problems here. First, by using connect on the server end, you're telling the operating system that you will only be communicating with IP address "192.168.67.42" port 5000. That is probably not what you intended. (A server usually talks to whatever client wants to talk to it.)
Second, by not specifying SOCK_DGRAM in your client, you're getting the default socket type, which is SOCK_STREAM. That means your client is trying to connect to your server on TCP port 80 -- not UDP port 80 (the two namespaces are totally separate).
For a UDP "session", both sides need an IP address and a port number. If you do not bind a port specifically, the operating system will choose one for you quasi-randomly. In order to link up client and server, they must agree on at least one of those.
So a typical UDP server will bind to a well-known port (presumably you intended 5000 for that purpose). Then the client can connect to the server at that port. The code would look something like this (sans error handling):
Server side:
# Create socket
s = socket(AF_INET, SOCK_DGRAM)
# Bind to our well known port (leave address unspecified
# allowing us to receive on any local network address)
s.bind(('', 5000))
# Receive from client (so we know the client's address/port)
buffer, client_addr = s.recvfrom(1024)
# Now we can send to the client
s.sendto(some_buffer, client_addr)
The client is close to what you have, but you should send some data from the client to the server first so that the server knows your address:
s = socket(AF_INET, SOCK_DGRAM)
# Create connection to server (the OS will automatically
# bind a port for the client)
s.connect((host, port))
# Send dummy data to server so it knows our address/port
s.send(b'foo')
buffer = s.recv(1024)
Note that because you have used connect on the client side, you've permanently specified your peer's address and don't need to use recvfrom and sendto.
On the client side, this is wrong:
s = socket.socket()
for receiving UDP packets, you need to create a UDP socket, same as you did on the server side:
s = socket(AF_INET, SOCK_DGRAM)
Also, if you want your client to be able to receive UDP packets you will need to bind() it to port 5000 (connect() is neither necessary nor sufficient for that).

Categories