how to do something like streams inside a port (Python socket) - python

there is such a code:
server:
import socket
from threading import Thread
from time import sleep
sock = socket.socket()
sock.bind(('', 1337))
sock.listen(1)
conn, addr = sock.accept()
def func1():
while True:
conn.send("1".encode("utf-8"))
sleep(0.5)
def func2():
while True:
conn.send("2".encode("utf-8"))
sleep(0.5)
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()
client:
import socket
from threading import Thread
from time import sleep
sock = socket.socket()
sock.connect(('localhost', 1337))
def func1():
while True:
data = sock.recv(1024).decode("utf-8")
if data != "1":
print("the package did not arrive properly")
else:
print("package arrived ok")
def func2():
while True:
data = sock.recv(1024).decode("utf-8")
if data != "2":
print("the package did not arrive properly")
else:
print("package arrived ok")
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()
I need to make sure that the packet sent by function1 comes to function1, and the packet of function2 comes to function2, but this code does not work correctly, and packets from function1 often end up in function2 and vice versa

I feel like you are approaching this from the wrong direction. You do not need multiple threads in the server or client. If you have multiple threads that is fine, but that's really not relevant for the problem you are having.
You are trying to multiplex multiple different types of messages over a single socket connections. In other words, you need a communication protocol.
On top of that, you have another problem that you do not appear to be aware of yet. Sockets are streams of bytes, in particular, they are not messages. If you send multiple messages in quick succession, they might be truncated or combined in the receiver.
If you send the following packages:
1
2
1
1
2
They could be received as follows:
12
112
Then your receiver will be very confused. Again, this problem can be resolved with a communication protocol.
There are many different ways to implement a communication protocol. The simplest that I can think of is to use JSON:
# sender.py
import socket
import time
import json
sock = socket.socket()
# https://stackoverflow.com/a/6380198/8746648
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', 1337))
sock.listen(1)
conn, addr = sock.accept()
while True:
# If necessary, you can make these calls from different threads.
# Notice, that we append a newline at the end, this is needed for 'readline' to work properly.
conn.send(json.dumps({ "type": 1, "payload": 42 }).encode("utf-8") + b"\n")
time.sleep(0.5)
conn.send(json.dumps({ "type": 2, "payload": "can-be-anything" }).encode("utf-8") + b"\n")
time.sleep(0.5)
# receiver.py
import socket
import json
sock = socket.socket()
sock.connect(('localhost', 1337))
# We know, that the messages themselves do not contain newline characters
# and the server sends a newline after each message, therefore, this will receive a complete message.
sock_file = sock.makefile()
while line := sock_file.readline():
object_ = json.loads(line)
# If you want to you can handle the messages in different threads.
# This could be done by setting up a queue that is consumed by working threads.
if object_["type"] == 1:
print(f"received(1): {object}")
elif object_["type"] == 2:
print(f"received(2): {object}")

If you are willing you could use multiple ports
<Client>
import socket
from threading import Thread
from time import sleep
def func1():
sock = socket.socket()
sock.connect(('localhost', 1338))
while True:
data = sock.recv(1024).decode("utf-8")
if data != "1":
print("the package did not arrive properly")
else:
print("package arrived ok")
def func2():
sock = socket.socket()
sock.connect(('localhost', 1337))
while True:
data = sock.recv(1024).decode("utf-8")
if data != "2":
print("the package did not arrive properly")
else:
print("package arrived ok")
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()
<Server>
import socket
from threading import Thread
from time import sleep
def func1():
sock = socket.socket()
sock.bind(('', 1338))
sock.listen(1)
conn, addr = sock.accept()
while True:
conn.send("1".encode("utf-8"))
sleep(0.5)
def func2():
sock = socket.socket()
sock.bind(('', 1337))
sock.listen(1)
conn, addr = sock.accept()
while True:
conn.send("2".encode("utf-8"))
sleep(0.5)
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()

Related

How to see that we've reached the end of the data for a socket connection?

Is there something the client needs to do in order to flag that "This is the end?"
For example, I have the following server running:
import socket, sys
while True:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 5500))
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
data = b''
while True:
data_chunk = conn.recv(10)
data += data_chunk
if not data: break
# How do I get here so I can echo the message *at the end* ?
# conn.send(b'Done. What you sent was: %s' % data)
And I have the following client code:
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('sandbox2.myip.com', 5500))
client_socket.send(b'select * from table')
# Now, what to do so that I can get the final message from he server?
When I do the connection though, this is what it shows:
sampleDB$ python listener.py
Connected by ('99.51.149.29', 63352)
I can confirm that the data data_chunks are being received, but then it just seems to hang at this part right here:
data_chunk = conn.recv(10)
Is there something I need to do in the client (or the server?) to flag that "This is the end of the transmission, so conn.recv() doesn't just hang indefinitely?
Here's a complete example of a socket based client/server protocol that implements the strategy described in my comment:
import socket
import threading
from struct import pack, unpack
HOST = 'localhost'
PORT = 7070
FORMAT = ('!Q', 8)
MSG = '''The Owl and the Pussy-cat went to sea
In a beautiful pea-green boat,
They took some honey, and plenty of money,
Wrapped up in a five-pound note.
The Owl looked up to the stars above,
And sang to a small guitar,
"O lovely Pussy! O Pussy, my love,
What a beautiful Pussy you are,
You are,
You are!
What a beautiful Pussy you are!"'''
def sendbuffer(s, b):
buffer = pack(FORMAT[0], len(b)) + b
offset = 0
while offset < len(buffer):
offset += s.send(buffer[offset:])
def recvbuffer(s):
p = s.recv(FORMAT[1], socket.MSG_WAITALL)
n = unpack(FORMAT[0], p)[0]
return None if n == 0 else s.recv(n, socket.MSG_WAITALL)
def server():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, _ = s.accept()
with conn:
while (data := recvbuffer(conn)):
sendbuffer(conn, data)
def client(msg):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
sendbuffer(s, msg.encode())
data = recvbuffer(s)
print(data.decode())
sendbuffer(s, b'') # kill switch
def main():
threading.Thread(target=server).start()
client(MSG)
if __name__ == '__main__':
main()

How to run two servers in one python code

I try to make a two udp listening servers in one python code code is below,
import threading
import time
import socket
class udpreceive:
def __init__(self,port,ip):
self.port = port
self.ip = ip
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind((self.ip, self.port))
def startserver(self):
while True:
time.sleep(1)
data, addr = self.sock.recvfrom(1024)
print (data)
server1 = udpreceive(514,"192.168.1.5")
s1 = threading.Thread(target=server1.startserver())
server2 = udpreceive(515,"192.168.1.5")
s2 = threading.Thread(target=server2.startserver())
s2.start()
s1.start()
this is client code for udp sender 1
import socket
import time
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
counter =0
while True:
send_data = "hellow world server1 :- "+ str(counter)
sock.sendto(send_data.encode(), ("192.168.1.5", 514))
print (send_data)
counter +=1
this is client code for sender 2
import socket
import time
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
counter =0
while True:
send_data = "hellow world server2 :- "+ str(counter)
sock.sendto(send_data.encode(), ("192.168.1.5", 514))
print (send_data)
counter +=1
When i run receive code its only show sender 1 data. start only sender 2 and start receive code but its not show any sender 2 sending data but i start sender 1 receive code show sender 1 data.
what is the wrong thing i do? i need to show both sender 1 and sender 2 data in receive program
im new to oop and socket programming
thanks
In threading module, "target" keyword argument should not contain brackets,
see How NOT to wait for a thread to finish in Python . As it should be:
threading.Thread(target=server1.startserver)
Then, the two UDP server threads shall start then join, as fairly sharing CPU resources is important (especially when using infinite loops).
The code for the server could be:
import threading
import time
import socket
class udpreceive:
def __init__(self,port,ip):
self.port = port
self.ip = ip
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind((self.ip, self.port))
def startserver(self):
while True:
data, addr = self.sock.recvfrom(1024)
print(f'port {self.port} receives {data}')
s1 = udpreceive(514, "192.168.1.5")
s2 = udpreceive(515, "192.168.1.5")
threads = [threading.Thread(target=s1.startserver), threading.Thread(target=s2.startserver)]
for th in threads:
th.start()
print(f'threads {th} started')
th.join(0.1)
Meanwhile, you may need to change the code in sender 2 to:
sock.sendto(send_data.encode(), ("192.168.1.5", 515)) # Send to port 515, not 514

Python Socket Call server.py and client.py in main.py

My question is that how to call server and client sequentially in main method ?
Problem is that python debugger waiting and be suck in line that calling the server(blocking the calling client line).
I tried threading but not work . Thanks for your attention.
IMPORTANT: Below codes using Python2
Main python file:
import xClient
import xServer
import threading
tempServer=xServer
tempClient=xClient
thrMain = threading.Thread(target=tempServer.innerClient.Main())
thrMain.start()
thrMain.join()
tempClient.innerClient.Main()
xClient.py : # STANDARD Client code and works correctly
import socket
import time
class innerClient:
def Main():
time.sleep(2)
host = '127.0.0.1'
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
message = "test message"
while True:
s.send(message.encode('ascii'))
data = s.recv(1024)
print('Received from the server :', str(data.decode('ascii')))
ans = raw_input('Continue(y/n) :')
if ans == 'y':
continue
else:
break
s.close()
xServer.py : # STANDARD Server code and works correctly
import socket
import threading
class innerServer:
print_lock = threading.Lock()
# thread fuction
def threaded(c):
while True:
data = c.recv(1024)
if not data:
print('See you later')
print_lock.release()
break
data = data[::-1]
c.send(data)
c.close()
def Main():
host = ""
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print("socket binded to post", port)
s.listen(5)
print("socket is listening")
while True:
c, addr = s.accept()
print_lock.acquire()
print('Connected to :', addr[0], ':', addr[1])
thr = threading.Thread(target=threaded, args=(c,))
thr.start()
thr.join()
s.close()
TCP Socket Diagram

Why won't this python socket chat server work correctly?

So I have made some code that follows. It is suppose to let a server and a client communicate... but it doesn't work.
Can someone explain why, or better yet fix my code???
Server.
import time
import socket
from threading import Thread
global sS
sS = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sS.bind(('', 2347))
sSconAddresses = []
sSconData = []
print(" Server : Running ... ")
sS.listen(10)
while True:
try:
cOn, aDr = sS.accept()
sSconAddresses.insert(0, str(aDr))
sSconData.insert(0, str(cOn))
time.sleep(0.3)
except:
time.sleep(0.1)
pass
def ConHandler():
for _ in sSconData:
PacketData = _.recv(700)
if not PacketData:
_.close()
else:
stringData = PacketData.decode('utf-8')
print(stringData)
sS.sendto(PacketData, _)
ConHandlerThread = Thread(target=ConHandler)
ConHandlerThread.daemon = True
ConHandlerThread.start()
Client.
import threading, time
import socket, sys
import os
global cS
cS = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cS.connect(('PRIVATE', 2347))
Server = ('PRIVATE', 2347)
while True:
PacketData = input(" Client> ")
ByteData = PacketData.encode('utf-8')
cS.sendto(ByteData, Server)
It doesn't return any errors so I am confused why it doesn't work.
First of all, in your server-side code, you're having a while True before starting your thread, so it can't work.
Then, if you succeed starting your thread by moving the code, its for will see an empty list, so it will not loop, and just exit right here.
Starting from your code, here's something that works:
The client:
import socket
def main():
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('127.0.0.1', 2345))
while True:
packetdata = input(" Client> ")
bytedata = packetdata.encode()
client_socket.send(bytedata)
print(client_socket.recv(700).decode())
if __name__ == '__main__':
main()
The server:
import socket
from threading import Thread
from queue import Queue
def client_handler(client_socket):
while True:
data = client_socket.recv(700)
print(data)
client_socket.send("Server {}".format(data.decode()).encode())
def conn_handler(conn_queue):
while True:
conn, address = conn_queue.get()
print("Handler getting a connection from {}".format(address))
client_thread = Thread(target=client_handler, args=(conn,))
client_thread.daemon = True
client_thread.start()
def main():
print("Server: Running ...")
conn_queue = Queue()
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(('', 2345))
server_socket.listen(10)
con_handler_thread = Thread(target=conn_handler, args=(conn_queue,))
con_handler_thread.daemon = True
con_handler_thread.start()
while True:
conn_queue.put(server_socket.accept())
if __name__ == '__main__':
main()
Note that this is suboptimal, starting one thread per client is not the way to go. The best way to handle this kind of situation is to keep everything in a single thread and use a select-like function to know what to do. However select is a bit limited too (like 1024 connections max, hardcoded in the libc), so the way to go is to use epoll / kqueue / whatever better than poll / select, and there's a module for this: https://docs.python.org/3/library/select.html
Yet using the select module is still the old, manual, cubersome way to express your needs, you should take a look at the coroutine based API of asyncio which enable a clear way to express the intention.
The asyncio equivalent may look like:
import asyncio
async def client():
reader, writer = await asyncio.open_connection('127.0.0.1', 8888)
while True:
message = input("Client> ")
writer.write(message.encode())
data = await reader.read(100)
print('Received: {}'.format(data.decode()))
loop = asyncio.get_event_loop()
loop.run_until_complete(client())
And, server side:
import asyncio
async def handle_client(reader, writer):
while True:
data = await reader.read(100)
if not data:
return
message = data.decode()
addr = writer.get_extra_info('peername')
print("Received %r from %r" % (message, addr))
print("Send: %r" % message)
writer.write(data)
await writer.drain()
loop = asyncio.get_event_loop()
coro = asyncio.start_server(handle_client, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)
print('Serving on {}'.format(server.sockets[0].getsockname()))
loop.run_forever()

Python UDP communication using Socket, check data received

I'm pretty new to the Python, trying to write a code to receive string from UDP connection, the problem I have now is that I need to receive data from 2 sources, I want the program continue looping if there is no data from either or both of them, but now if there is no data from source 2, it will stop there and wait for the data, how to solve it?
I was thinking about using if statement, but I don't know how to check if the incoming data is empty of not, any ideas will be appreciated!
import socket
UDP_IP1 = socket.gethostname()
UDP_PORT1 = 48901
UDP_IP2 = socket.gethostname()
UDP_PORT2 = 48902
sock1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock1.bind((UDP_IP1, UDP_PORT1))
sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock2.bind((UDP_IP2, UDP_PORT2))
while True:
if sock1.recv != None:
data1, addr = sock1.recvfrom(1024)
data1_int = int(data1)
print "SensorTag[1] RSSI:", data1_int
if sock2.recv != None:
data2, addr = sock2.recvfrom(1024)
data2_int = int(data2)
print "SensorTag[2] RSSI:", data2_int
If select doesn't work out for you you can always throw them into a thread. You'll just have to be careful about the shared data and place good mutex around them. See threading.Lock for help there.
import socket
import threading
import time
UDP_IP1 = socket.gethostname()
UDP_PORT1 = 48901
UDP_IP2 = socket.gethostname()
UDP_PORT2 = 48902
sock1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock1.bind((UDP_IP1, UDP_PORT1))
sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock2.bind((UDP_IP2, UDP_PORT2))
def monitor_socket(name, sock):
while True:
sock.recv is not None:
data, addr = sock.recvfrom(1024)
data_int = int(data)
print(name, data_int)
t1 = threading.Thread(target=monitor_socket, args=["SensorTag[1] RSSI:", sock1
t1.daemon = True
t1.start()
t2 = threading.Thread(target=monitor_socket, args=["SensorTag[2] RSSI:", sock2])
t2.daemon = True
t2.start()
while True:
# We don't want to while 1 the entire time we're waiting on other threads
time.sleep(1)
Note this wasn't tested due not having two UPD sources running.

Categories

Resources