Unable to communicate with proxy/server application - python

I am having issue with below code in TCP python socket prog. I am trying to send integer messages from (lets say) 3 clients. So, There is 3 clients, so the proxy knows that N = 3, and it will wait until it receives 3 numbers. 1st client sends 10 to the proxy, 2nd client sends 20 to the proxy, and the 3rd client sends 30 to the proxy. Because N is reached, the proxy starts to transmit to the server. It will send (in order): 10, 20, 30, END (where every comma indicates a new message). The server receives the 4 messages, and after receiving the END message, it starts to calculate the average. The average is 20, so the server sends 20 to the proxy, and closes the connection. The proxy receives 20, and sends it to all the 3 clients, and then closes the connection. The clients receive 20.
Please check below code and let me know where I am making mistake... I am able to send number from client but not getting response from proxy/server. Am I doing any mistake ?
For client:
#!/usr/bin/env python
import socket
HOST = 'localhost'
PORT = 21001
proxysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
proxysock.connect((HOST, PORT))
while True:
try:
data = str(raw_input())
except valueError:
print 'invalid number'
proxysock.sendall(data)
data = proxysock.recv(1024)
print 'server reply:' +data
proxysock.close()
For Proxy:
#!/usr/bin/env python
import select
import sys
import socket
from thread import *
HOST = 'localhost'
PORT = 21001
PORT1 = 22000
max_conn = 5
buffer_size = 2048
proxyserversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
proxyserversock.bind((HOST, PORT))
proxyserversock.listen(max_conn)
input = [proxyserversock,sys.stdin]
running = 1
while running:
inputready,outputready,exceptready = select.select(input,[],[])
for proxysock in inputready:
if proxysock == proxyserversock:
client_sock, addr = proxyserversock.accept()
input.append(client_sock)
elif proxysock == sys.stdin:
junk = sys.stdin.readline()
running = 0
else:
data = proxysock.recv(buffer_size)
if data:
proxysock.send(data)
else:
proxysock.close()
input.remove(proxysock)
serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversock.connect((HOST, PORT1))
serversock.sendall(data,END)
serversock.recv(buffer_size)
client_sock.sendall()
serversock.close()
client_sock.close()
For Server:
#!/usr/bin/env python
import socket
HOST = 'localhost'
PORT1 = 22000
serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversock.bind((HOST, PORT1))
serversock.listen(10)
while 1:
serversock, addr = serversock.accept()
data = serversock.recv(2048)
data.pop()
average = float(sum(data))/len(data)
serversock.sendall(average)
print 'avg' + average
serversock.close()

Related

Python socket library: OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected

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.
I am getting the above error..My server and client can send and receive their first messages but I get this error if I try to send more than one message.
My Server Code is here
import socket
import threading
import time
from tkinter import *
#functions
def t_recv():
r = threading.Thread(target=recv)
r.start()
def recv():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as listensocket:
port = 5354
maxconnections = 9
ip = socket.gethostbyname(socket.gethostname())
print(ip)
server = (ip, port)
FORMAT = 'utf-8'
listensocket.bind((server))
listensocket.listen(maxconnections)
(clientsocket, address) = listensocket.accept()
msg = f'\[ALERT\] {address} has joined the chat.'
lstbox.insert(0, msg)
while True:
sendermessage = clientsocket.recv(1024).decode(FORMAT)
if not sendermessage == "":
time.sleep(3)
lstbox.insert(0, 'Client: ' +sendermessage)
def t_sendmsg():
s = threading.Thread(target=sendmsg)
s.start()
at = 0
def sendmsg():
global at
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as g:
hostname = 'Lenovo-PC'
port = 5986
if at==0:
g.connect((hostname, port))
msg = messagebox.get()
lstbox.insert(0, 'You: ' +msg)
g.send(msg.encode())
at += 1
else:
msg = messagebox.get()
lstbox.insert(0, 'You: ' +msg)
g.send(msg.encode())
And my client code is same with minor difference
import socket
import time
import threading
from tkinter import *
#functions
def t_recv():
r = threading.Thread(target=recv)
r.start()
def recv():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as listensocket:
port = 5986
maxconnections = 9
ip = socket.gethostname()
print(ip)
FORMAT = 'utf-8'
host = 'MY_IP' # My actual ip is there in the code
listensocket.bind((host, port))
listensocket.listen(maxconnections)
(clientsocket, address) = listensocket.accept()
while True:
sendermessage = clientsocket.recv(1024).decode(FORMAT)
if not sendermessage == "":
time.sleep(3)
lstbox.insert(0, 'Server: ' +sendermessage)
def t_sendmsg():
s = threading.Thread(target=sendmsg)
s.start()
at = 0
def sendmsg():
global at
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as g:
hostname = 'Lenovo-PC'
port = 5354
if at==0:
g.connect((hostname, port))
msg = messagebox.get()
lstbox.insert(0, 'You: ' +msg)
g.send(msg.encode())
at += 1
else:
msg = messagebox.get()
lstbox.insert(0, 'You: ' +msg)
g.send(msg.encode())
Please let me know what changes are required to be made in order to make it run for every message.
I tried to put
g.connect((hostname, port))
the above line in the loop so that it will connect every time loop iterates. But it did not help.
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as g:
...
if at==0:
g.connect((hostname, port))
...
g.send(msg.encode())
at += 1
else:
...
g.send(msg.encode())
In the if at==0 condition it connects to the server, in the else part not. But is still trying to send something on the not connected socket.

Python socket hangs on connect/accept

I'm trying to send packets using sockets, and was able to do so just fine until this morning. I'm not sure what's going on. The packets are showing up in tcpdump but the server and the client cannot connect to each other.
netcat.py
import socket
import argparse
import sys
import os
import re
import threading
def convertContent(content: str = "") -> bytes:
byteContent = []
# grab the hex from the content
for i in range(len(content)):
if content[i] == "\\" and content[i+1] == "x":
byteContent.append(f"{content[i+2]}{content[i+3]}")
# grab the non hex from the content, split it on the hex
stringContent = re.split(r"\\x.{2}", content)
byteIndex = 0
newContent = b""
# Re add the non-hex content, and the hex content
for word in stringContent:
newContent += word.encode()
if byteIndex < len(byteContent):
newContent += bytes.fromhex(byteContent[byteIndex])
byteIndex += 1
newContent = newContent.replace(b"\\n", b"\n").replace(b"\\r", b"\r")
return newContent
class Netcat():
'''
Netcat class that can be used to send/receive TCP packets
'''
BUFFER_SIZE = 1024
def __init__(self):
pass
#classmethod
def createSocket(cls):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Address might be in a TIME_WAIT status, ignore this
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Port might be in a TIME_WAIT status, ignore this
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
return sock
#classmethod
def send(cls, hostname: str = "127.0.0.1", srcPort: int = 0, destPort: int = 9999, content: str = "", buffer_size: int = 1024):
srcPort = int(srcPort)
destPort = int(destPort)
try:
content = convertContent(content=content)
except:
pass
sock = cls.createSocket()
# Set the source port before sending
sock.connect((hostname, destPort))
sock.sendall(content)
# shutdown might be redundant/unnecessary (tells connected host that we're done sending data)
sock.shutdown(socket.SHUT_WR)
while True:
data = sock.recv(buffer_size)
if len(data) == 0:
break
sock.close()
#classmethod
def receive(cls, port: int = 9999, buffer_size: int = 1024):
if port <= 1024 and os.geteuid() != 0:
print(f"Listening on port {port} requires superuser privileges!")
return
host = ""
sock = cls.createSocket()
sock.bind((host, port))
sock.listen(10)
conn, addr = sock.accept()
while True:
data = conn.recv(buffer_size)
if not data:
break
conn.close()
threading.Thread(target=Netcat.receive,daemon=True).start()
Netcat.send(content="test")
Note: I am sending the packets from one VM to another, rather than sending to myself, but it would be a lot to ask people to spin up a bunch of VMs to reproduce this. The hostname param in the send method should be the actual IP of the receiving machine
I've thrown some print statements, and the server stops on sock.accept(), while the client hangs on sock.connect((hostname, destPort))
I checked the hostname for the server, and it's listening on (0.0.0.0, 8888) (assuming 8888 is the port param), which means its listening on all interfaces on that port, so I dont know why its refusing to connect
I tcpdumped on the server, and its getting the packets, it gets a SYN, then sends out a SYN, ACK, but the rest of the packets are marked as re-transmissions.
I've tried looping the accept & connect lines, thinking maybe some sort of race condition was occurring, but no matter what I do the client can't connect to the server.
Edit: This works on my local machine, but still breaks when I try to send packets over the network. The first 2 steps of the handshake go through SYN & SYN, ACK, but not the third ACK
Don't bind in the client. Working example below, but minor changes to make a standalone script:
import socket
import threading
def receive(port: int = 9999, buffer_size: int = 1024):
host = ""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Address might be in a TIME_WAIT status, ignore this
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((host, port))
sock.listen()
conn, addr = sock.accept()
while True:
data = conn.recv(buffer_size)
if not data:
break
print(data)
conn.close()
def send(hostname: str = "127.0.0.1", destPort: int = 9999, content: str = b"test", buffer_size: int = 1024):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Address might be in a TIME_WAIT status, ignore this
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Removed bind
sock.connect((hostname, destPort))
sock.sendall(content)
# shutdown might be redundant/unnecessary (tells connected host that we're done sending data)
sock.shutdown(socket.SHUT_WR)
while True:
data = sock.recv(buffer_size)
if len(data) == 0:
break
sock.close()
threading.Thread(target=receive,daemon=True).start()
send()
Output:
b'test'

sending the message to multiple clients and receiving the message from multiple clients

I'm trying to send the command from the server to the connected clients and trying to receive the response.
But connectionList[i].recv(2048) breaking the while loop. I want the server to ask for the "Enter the command" repeatedly. but the loop is not repeating once it's receiving the response from clients
Here is my code
import socket
import sys
from _thread import *
import threading
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
host = socket.gethostname()
server_address = ("0.0.0.0", 8765)
sock.bind(server_address)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#Listen for incoming connections
sock.listen(5)
print ("Waiting for connection...")
#Variable for the number of connections
numbOfConn = 0
ThreadCount = 0
#Name of list used for connections
addressList = []
connectionList = []
#Function that continuosly searches for connections
def clients(connectionList, addressList):
while True:
cmd=input("Enter input command:")
#for loop to send message to each
for i in range(0,numbOfConn):
connectionList[i].sendto(str.encode(cmd), addressList[i])
while True:
for i in range(0,numbOfConn):
response = connectionList[i].recv(2048)
#break
print("response")
if(response.decode('utf-8') =="done"):
print("Exiting the loop")
break
#connection.close()
while True:
#accept a connection
connection, address = sock.accept()
print ('Got connection from', address)
numbOfConn += 1
addressList.append((address))
connectionList.append((connection))
#Thread that calls the function: clients and stores them in a tuple called connection
start_new_thread(clients, (connectionList, addressList))
ThreadCount += 1
print('Thread Number: ' + str(ThreadCount))
sock.close()
could you please help me to find out the issue?

Client cannot receive UDP message

I am a beginner of socket programming using python. I am working on my course project. Part of my project requires sending and receiving UDP messages with different port. The server program called robot is provided and I need to write the client program called student which can interact with the robot. Thus, I cannot show all source code in the server program.
This is the part related to the UDP socket in the server program
############################################################################# phase 3
# Create a UDP socket to send and receive data
print ("Preparing to receive x...")
addr = (localhost, iUDPPortRobot)
s3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s3.bind(addr)
x, addr = s3.recvfrom(1)
print ("Get x = %d" % (int(x)))
############################################################################# phase 3
time.sleep(1)
print ("Sending UDP packets:")
messageToTransmit = ""
for i in range(0,int(x) * 2):
messageToTransmit += str(random.randint(0,9999)).zfill(5)
print ("Message to transmit: " + messageToTransmit)
for i in range(0,5):
s3.sendto(messageToTransmit.encode(),(studentIP,iUDPPortStudent))
time.sleep(1)
print ("UDP packet %d sent" %(i+1))
############################################################################# phase 4
This is my client program. s3 is the UDP socket. I can send message to the server program successfully but I cannot receive the message from it. Is this due to the difference in the ports? If yes, what should I do in order to fix it?
import os
import subprocess
import socket
import random
import time
sendPort = 3310
localhost = '127.0.0.1'
socket.setdefaulttimeout(10)
command = "python robot_for_python_version_3.py"
subprocess.Popen(command)
print("ROBOT IS STARTED")
sendSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sendSocket.connect((localhost, sendPort))
studentId = '1155127379'
sendSocket.send(studentId.encode())
s_2Port = sendSocket.recv(5)
sendSocket.close()
s_2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s_2.bind((localhost, int(s_2Port)))
s_2.listen(5)
s2, address = s_2.accept()
s_2.close()
step4Port = s2.recv(12)
iUDPPortRobot, dummy1 = step4Port.decode().split(",")
iUDPPortStudent, dummy2 = dummy1.split(".")
s3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
num = random.randint(5,10)
time.sleep(3)
s3.sendto(str(num).encode(), (localhost, int(iUDPPortRobot)))
print("Test1")
charStr = s3.recvfrom(1024)
print("Test2")
print(charStr)
exit()
The reason why you are not receiving the message is because the server sends it to an endpoint that is not listening for messages. As the protocol is UDP (no guarantees, etc.), the server sends the message successfully to a non-listening endpoint, while the listening endpoint waits forever.
In more detail, addr as returned by x, addr = s3.recvfrom(1) is not (studentIP, iUDPPortStudent). Try the following to see the difference (note that you have omitted the piece where iUDPPortRobot is defined and shared, I set it to 50000 for illustration purposes):
# in one interactive session 1 (terminal), let's call it session 1
>>> import socket
>>> import random
>>> import time
>>>
>>> iUDPPortRobot = 50000
>>> addr = ('localhost', iUDPPortRobot)
>>> s3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s3.bind(addr)
>>> x, addr = s3.recvfrom(1) # <= this will block
# in another interactive session (terminal), let's call it session 2
>>> import socket
>>> import random
>>> import time
>>>
>>> iUDPPortRobot = 50000
>>> s3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> num = random.randint(5,10)
>>> s3.sendto(str(num).encode(), ('localhost', int(iUDPPortRobot))) # <= this will unblock recvfrom in session 1, i.e., the message got received
1
# back to session 1
>>> addr <= check address, this is the main issue you are facing
('127.0.0.1', 60911)
>>> messageToTransmit = ""
>>> for i in range(0,int(x) * 2):
... messageToTransmit += str(random.randint(0,9999)).zfill(5)
...
>>> print ("Message to transmit: " + messageToTransmit)
Message to transmit: 06729020860821106419048530205105224040360495103025
# back to session 2, let's prepare for receiving the message
>>> charStr = s3.recvfrom(1024) # <= this will block
# back to session 1 to send a message
# you do not share what (studentIP,iUDPPortStudent), but from
# what you describe it is not ('127.0.0.1', 60911), let's say
# studentIP = 'localhost' and iUDPPortStudent = 50001
>>> studentIP = 'localhost'
>>> iUDPPortStudent = 50001
# now let send a message that will be sent successfully but not received, i.e.,
# it will not unblock recvfrom in session 2
>>> s3.sendto(messageToTransmit.encode(),(studentIP,iUDPPortStudent))
50
# ... but if try to send to the listening endpoint it will get received
>>> s3.sendto(messageToTransmit.encode(), addr)
50
# back to session 2, to check things
>>> charStr
(b'06729020860821106419048530205105224040360495103025', ('127.0.0.1', 50000)) # <= SUCCESS
There are two ways to fix this. The one shown above which involves changing the server code, which essentially involves what is shown above, i.e., send the message to a listening endpoint by modifying the address passed to s3.sendto. If I understand things correctly, this is not an option as you are trying to write the client code. The second way is to send the message to (studentIP, iUDPPortStudent), but have a listening endpoint at the other end. If studentIP and iUDPPortStudent are known to your "client" program, which I assume is the case, you can add code similar to what you have at the top of the server program code snippet.
Specifically, add in place of charStr = s3.recvfrom(1024) something like:
addr = (studentIP, iUDPPortStudent)
s4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s4.bind(addr)
charStr = s4.recvfrom(1024) # <= this will block and unblock when you send the message using s3.sendto(messageToTransmit.encode(),(studentIP,iUDPPortStudent))
For completeness, you will need to change localhost to 'localhost' and if in your experiments you encounter a OSError: [Errno 98] Address already in use you will have to wait for the TIME-WAIT period to pass or set the SO_REUSEADDR flag by adding s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) before bind.

Python - counting times a server receives request from client?

I'm playing around with python lately and trying to learn how to build a python server, using TCP connections.
I have this code that runs a server...
import socket
from threading import *
import datetime
import time
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "localhost"
port = 8000
print (host)
print (port)
serversocket.bind((host, port))
class client(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.start()
def run(self):
while 1:
st = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
#cName =
print(self.sock.recv(1024).decode()+' sent # '+ st + ':' , self.sock.recv(1024).decode())
self.sock.send(b'Processing!')
serversocket.listen(5)
print ('server started and listening')
while 1:
clientsocket, address = serversocket.accept()
client(clientsocket, address)
And two of these client.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host ="localhost"
port =8000
cName = 'client 2' # or client 1
s.connect((host,port))
def ts(str):
s.sendall(cName.encode())
s.send('e'.encode())
data = ''
data = s.recv(1024).decode()
print (data)
while 2:
r = input('enter')
ts(s)
s.close ()
I want to know how to allow the server to count and keep track of how many times it recieves a message from both client 1 and client 2.
For example, if server starts at count of 0 (e.g. count = 0). And each time client 1 or client 2 sends back a message or in this case, hits enter, the count will go up (count += 1). If I call for a print(count), the output should be 1.
Thanks?
I think you can create a global variable (say count=0) in your first script (server script) and keep incrementing the value every time you receive the message from a client.
So your run method can become,
def run(self):
global count
while 1:
st = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
#cName =
print(self.sock.recv(1024).decode()+' sent # '+ st + ':' , self.sock.recv(1024).decode())
count += 1
self.sock.send(b'Processing!')
If you want the count to be client specific then create a dictionary of counts instead of a single integer and keep incrementing the respective integer on verifying some thing about a client.

Categories