How to initiate a socket connection from server to client? - python-3.x

I have setup a tcp socket between a client and a server, very basic. Client side:
#!/usr/bin/env python3
import socket
# create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = "81.88.95.250"
port = 25000
# connection to hostname on the port.
s.connect((host, port))
# Receive no more than 1024 bytes
msg = s.recv(1024)
s.close()
print (msg.decode('ascii'))
server side:
#!/usr/bin/env python3
import socket
# create a socket object
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = socket.gethostname()
port = 25000
# bind to the port
serversocket.bind((host, port))
# queue up to 5 requests
serversocket.listen(5)
while True:
# establish a connection
clientsocket,addr = serversocket.accept()
print("Got a connection from %s" % str(addr))
msg = 'Thank you for connecting'+ "\r\n"
clientsocket.send(msg.encode('ascii'))
clientsocket.close()
My target is to send notification from client to server, and that's easy. The difficult part is that I also need in some circumstances to start the connection from the server and to send a command to the client and this must be executed as soon as it is received, so I cannot setup a periodic "poll". But I'm quite confused on this part, because the client is behind a NAT, not exposed with a public IP.

Related

Should I change socket options on the original socket or the new one?

Consider the following python script:
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0', 9999))
s.listen()
connections = []
while True:
time.sleep(1)
conn, addr = s.accept()
connections.append(conn)
# send and receive data using open connections
According to the socket documentation:
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.
Now suppose I want to change the socket options, like:
setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2048)
Should I call this method on the original socket s, the new connection conn or both of them?

Don't understand why server won't respond to client (even after turning of firewall | Python | Server

I set up my server on MacBook air and my client is connecting from a Windows 10 machine. I turned off all security and firewalls on both machines (because that's what you do when you've lost all hope) and tried to connect from my windows machine multiple times, but to no avail. I'm on the same network btw (not using a VM).
Error:
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
Server:
import socket, threading
import multiprocessing
from time import sleep
# tells us the bytes of the message
HEADER = 64
PORT = 5430
# or you could do socket.gethostbyname(socket.gethostname())
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = '!END'
# defines the type of connection
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
def start():
server.listen()
print(f'[LISTENING] Server is listening on {SERVER}')
while True:
conn, addr = server.accept()
print('[ACTIVE CONNECTIONS] 1')
start()
Client:
from time import sleep
import socket, subprocess
HEADER = 64
PORT = 5430
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = '!END'
SERVER = '192.32.322.3'
ADDR = (SERVER, PORT)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)

I'm trying to make chat program using Python 3.6 but I think I can't retain connection

import socket
host = 'address' # as you know this isn't letters but I just write it as address for now.
port = 50000
bufsize = 1024
server = socket.socket()
server.bind((host, port))
server.listen(5)
while 1:
print("Waiting Connection")
client, address = server.accept()
print("Connected")
welcomemsg = ("send messages")
client.send(bytes(welcomemsg, "utf-8"))
print("client info")
print(address)
msgfromclient = server.recv(bufsize).decode("utf8")
client.send(bytes(msgfromclient, "utf-8"))
import socket
bufsize = 1024
client = socket.socket()
while 1:
client.connect(('address', 50000))
welcomemsg = client.recv(bufsize).decode("utf8")
print(welcomemsg)
msgtoserver = input()
server.send(bytes(msgtoserver, "utf-8"))
msgfromserver = client.recv(bufsize).decode("utf8")
print(msgfromserver)
I think I can connect server and client and then I can make server send a welcome message to client and client can receive that message.
But after that I think I can't retain connection between server and client any longer.
I want to make server and client retain connection after server send a welcome message to client and client send a message to server and then server send it again to all the clients (yes I am trying to make chat program.)
I am using Windows.

Can't set timeout for python 3 recv

I am trying to get a time out on the code below. But it just hangs at the recv and never times out. Can someone point to what I am doing wrong? I have looked and I can't seem to find too much on it.
import socket
host = "localhost"
port = 8888
# create socket object
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# give object the ip and port to listen on
server_address = (host, port)
print('starting up on %s port %s' % server_address)
sock.bind(server_address)
# how many listeners
sock.listen(0)
# sets the time out
sock.settimeout(10)
while True:
print('waiting for a connection')
try:
#this waits for a connection from the sending side.
connection, client_address = sock.accept()
print('connection from', client_address)
start = False
message = ""
while client_address != "":
#this listens and waits for data to be sent and sets it to the data variable
data = connection.recv(32000).decode()
You have set an accept timeout on the listening socket, not a read timeout on the receiving socket.

python3: two clients sending data to server using sockets

I'm working with 3 raspberry pi, one as a server and the two others are clients. What I want to do is to make the clients communicate with the server simultaneously, I don't want to wait for client1 communication to be done in order to launch client2 request to the server (which I succeeded to do). However, I want each client to send different data to server at the same time. I tried to use Sockets and threading, like below.
server code:
import socket
import RPi.GPIO as GPIO
from threading import Thread
# Multithreaded Python server : TCP Server Socket Thread Pool
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print ("[+] New server socket thread started for " + ip + ":" + str(port))
def run(self):
while True :
data = conn.recv(2048)
data = data.decode('utf-8')
print ("Server received data:", data)
MESSAGE = input("Multithreaded Python server : Enter Response from Server/Enter exit:")
if MESSAGE == 'exit':
break
conn.send(str.encode(MESSAGE)) # echo
# Multithreaded Python server : TCP Server Socket Program Stub
TCP_IP = ''
TCP_PORT = 9050
BUFFER_SIZE = 2000 # Usually 1024, but we need quick response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(2)
threads = []
list_data=[]
while True:
print ("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip,port)) = s.accept()
data = conn.recv(2048)
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
list_data.append(data)
for t in threads:
t.join()
client1 code:
import socket
import RPi.GPIO as GPIO
import time
host = '192.168.0.198'
port = 9050
BUFFER_SIZE = 2000
MESSAGE = input("tcpClient1: Enter message/ Enter exit:")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while MESSAGE != 'exit':
s.send(str.encode(MESSAGE))
data = s.recv(BUFFER_SIZE)
data = data.decode('utf-8')
print (" Client2 received data:", data)
MESSAGE = input("tcpClient2: Enter message to continue/ Enter exit:")
client2 code:
import socket
import RPi.GPIO as GPIO
import time
import socket
host = '192.168.0.198'
port = 9050
BUFFER_SIZE = 2000
MESSAGE = input("tcpClient2: Enter message/ Enter exit:")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while MESSAGE != 'exit':
s.send(str.encode(MESSAGE))
data = s.recv(BUFFER_SIZE)
data = data.decode('utf-8')
print (" Client received data:", data)
MESSAGE = input("tcpClient2: Enter message to continue/ Enter exit:")
when i run, i obtain:
in the server terminal:
Multithreaded Python server : Waiting for connections from TCP clients...
[+] New server socket thread started for 192.168.0.197:47012
Multithreaded Python server : Waiting for connections from TCP clients...
[+] New server socket thread started for 192.168.0.196:47886
Multithreaded Python server : Waiting for connections from TCP clients...
in client1 terminal:
tcpClient1: Enter message/ Enter exit:begin
in client2 terminal:
tcpClient2: Enter message/ Enter exit:begin
It seems like server didn't receive or send any data.
As #Hikke mentioned in his comment, your server receives at two different places. The conn.recv call in this code snippet eats up the data that the server receiving thread is expecting. Remove data = conn.recv(2048) in your server's main loop:
while True:
print ("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip,port)) = s.accept()
data = conn.recv(2048) # <== dont eat the data of your thread here!
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
list_data.append(data)

Resources