Why I have some packets lost in localhost? - python

I try to develop a server and a client programs in Python 2.7, which can switch in UDP or in TCP, based on this echo program :
TCP vs. UDP socket latency benchmark
For now, i just try to program it as local host
When i run it in TCP (is_UDP = False), the server program shows me that there is no packet lost (total_perdu = 0)
But if i run it in UDP (is_UDP = True), it gives me some packets lost.
This is my code for the server :
import socket
from numpy import *
server_address = ("127.0.0.1", 4444)
client_address = ("127.0.0.1", 4445)
bufferSize = 4096
# is_UDP = True
is_UDP = False
# Create a datagram socket
if is_UDP == True:
UDP_Server_Socket_in = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
UDP_Server_Socket_in.bind(server_address)
UDP_Server_Socket_out = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
UDP_Server_Socket_out.connect(client_address)
connection = UDP_Server_Socket_in
print("UDP server is running...")
else :
TCP_Server_Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
TCP_Server_Socket.bind(server_address)
TCP_Server_Socket.listen(1)
connection, client_address = TCP_Server_Socket.accept()
print("TCP server is running...")
t = 0
total_perdu = 0
i = 0
while(True):
i += 1
# Receive packet from client
data_2= connection.recv(bufferSize)
tab=fromstring(data_2,dtype="int32")
size=len(data_2)
while size<bufferSize:
data_2= connection.recv(bufferSize-size)
size+=len(data_2)
if data_2:
perdu=int(tab[0])-t-1
sperdu=""
if perdu>0:
total_perdu+=perdu
sperdu = "(%d)"%(perdu)
print "Receive data : %s %d %d %s" % (tab[0], len(tab), total_perdu,sperdu)
t=int(tab[0])
And this is my code for the client:
import socket
from numpy import *
import time
server_address = ("127.0.0.1", 4444)
client_address = ("127.0.0.1", 4445)
# Packets variables
packet_size = 1024
total_packet = 1000
bufferSize = 4*packet_size
# Variables initialization
error = 0
total_throughput = 0
total_latene = 0
total_ratio = 0
total_stop_time_1 = 0
total_stop_time_3 = 0
# Creation of a packet
send_tab = zeros(packet_size, int)
for i in range(0, packet_size):
send_tab[i] = i
data_size = (send_tab.size+8)*send_tab.itemsize
print "Data size : %d" % data_size
print "Tab : %s \n" % send_tab
# is_UDP = True
is_UDP = False
# Create a socket at client side
if is_UDP == True:
UDP_Client_Socket_out = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
UDP_Client_Socket_out.connect(server_address)
UDP_Client_Socket_in = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
UDP_Client_Socket_in.bind(client_address)
connection = UDP_Client_Socket_out
print("UDP client is running...")
else:
TCP_Client_Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
TCP_Client_Socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 0)
TCP_Client_Socket.connect(server_address)
connection = TCP_Client_Socket
print("TCP client is running...")
start_time_0 = time.clock()
for packet_number in range(0,total_packet):
send_tab[0] = packet_number
# Send packet to server
start_time=time.clock()
sent = connection.send(send_tab)
if sent:
stop_time_1 = time.clock() - start_time
# Calculate throughput and ratio
throughput = data_size / (stop_time_1 * 1000000)
print "stop_time_1 \t%f" % stop_time_1
total_throughput += throughput
stop_time_3 = (time.clock() - start_time_0)
print "Results : \n"
print " Packet error : %d \n" % error
print " Thoughput: %f Mo/s \n " % (total_throughput/total_packet)
print " total_stop_time_1 : %f s \n " % (total_stop_time_1/total_packet)
print " stop_time_3 : %f \n" % stop_time_3
So, I have 3 questions about it :
Is it normal to have some packets which are lost even if I do it as a local host?
If yes, why?
Will I have the same problem if I program it in C?

From your code it looks like you expect to receive the UDP packets in the same order you are sending them. I don't think you are loosing packets, but rather the order in which they are received by the server is not the expected one (which is normal for UDP).
Also, you should take into consideration that UDP does not guarantee neither the order or the receiving of packets so your program should take this into consideration.
I would refactor the code and add the tab into a list, then sort it and check for the gaps (at the end of transmission).
Another way would be to send a reply from the server and make the check on the client (but this might increase the number if you deploy it on the Internet).

Related

The server is not terminated

I'm using threads to have a server listening for both TCP and UDP messages. Here is the code:
from threading import Thread
import time
import socket
Listening_Port = 5005
Listening_IP = "127.0.0.1"
#define UDP listening function
def UDPListen():
BUFFER_SIZE = 1024
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # IPv4, UDP
sock.bind((Listening_IP, Listening_Port))
while True:
data, address = sock.recvfrom(BUFFER_SIZE)
print "UDP Messsage from address: ", address
print "Message: ", data
#define a TCP listening function
def TCPListen():
BUFFER_SIZE = 1024
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4, TCP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((Listening_IP, Listening_Port))
while True:
sock.listen(1)
conn, address = sock.accept()
print "TCP connection from", address
data = conn.recv(BUFFER_SIZE)
print "Mesage: ", data
conn.close()
# main function
def main():
ThreadUDP = Thread(target=UDPListen)
ThreadTCP = Thread(target=TCPListen)
print "Starting Server..."
ThreadUDP.start()
ThreadTCP.start()
print "Server Started!"
if __name__ == "__main__":
main()
The problem is that when I press ctrl + c (even multiple times), the program is not terminated and I should close the console.
I tried something like this for def main(), but it didn't work:
def main():
ThreadUDP = Thread(target=UDPListen)
ThreadTCP = Thread(target=TCPListen)
try:
print "Starting Server..."
ThreadUDP.start()
ThreadTCP.start()
print "Server Started!"
# Hit Break / Ctrl-C to exit
except KeyboardInterrupt:
print('\nClosing')
raise
Updated code according to the solution offered in the answers:
from threading import Thread
import time
import socket
Listening_Port = 5005
Listening_IP = "10.0.0.3"
#define UDP listening function
def UDPListen():
BUFFER_SIZE = 1024
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # IPv4, UDP
sock.bind((Listening_IP, Listening_Port))
while not eve.isSet():
data, address = sock.recvfrom(BUFFER_SIZE)
print "UDP Messsage from address: ", address
print "Message: ", data
#define a TCP listening function
def TCPListen():
BUFFER_SIZE = 1024
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4, TCP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((Listening_IP, Listening_Port))
while not eve.isSet():
sock.listen(1)
conn, address = sock.accept()
print "TCP connection from", address
data = conn.recv(BUFFER_SIZE)
print "Mesage: ", data
conn.close()
# main function
def main():
ThreadUDP = Thread(target=UDPListen)
ThreadTCP = Thread(target=TCPListen)
eve = threading.Event()
print "Starting Server..."
ThreadUDP.start()
ThreadTCP.start()
print "Server Started!"
try:
while True:
eve.wait(2)
except Exception:
eve.set()
if __name__ == "__main__":
main()
but I received an error:
NameError: Global name 'threading' is not defined
the problem you have is that you run your listeners in a thread - meaning that signals caught in the main should somehow signal the threads.
use threading.Event and then in the main function :
eve = threading.Event()
<start your threads>
try:
while True:
eve.wait(2)
except Exception
eve.set()
and in the threads instead of while True use while not eve.isSet():

Client - Server socket programming with python

Below are my three scripts. I need to send the message from sricpt 1(Sensor.py) to script 2.(Client.py). And then the script 2 should send the message to script 3(Server.py).
It works fine till script 2 but the message isn't being received at the script 3 and the recvfrom() keeps waiting. There is no error but the script 3 doesn't show the message. Im using UDP. Please help.
SCRIPT 1(Sensor.py)
from socket import *
from time import ctime
CLIENT_IP = '192.168.1.109'
PORT = 23567
BUFSIZE = 1024
ADDR = (CLIENT_IP, PORT)
udpCliSock = socket(AF_INET, SOCK_DGRAM)
while True:
sendData = input("> ")
if sendData is None:
break
udpCliSock.sendto(sendData.encode(), ADDR)
udpCliSock.close()
SCRIPT 2(Client.py)
from socket import *
from time import ctime
HOST = '192.168.1.103'
CLIENT_IP='192.168.1.109'
PORT = 5005
SENSOR_PORT_NO=23567
BUFSIZE = 1024
ADDR = (HOST, PORT)
CLIENT_ADDR=(CLIENT_IP,SENSOR_PORT_NO)
udpCliSock = socket(AF_INET, SOCK_DGRAM)
client = socket(AF_INET, SOCK_DGRAM)
client.bind(CLIENT_ADDR)
while True:
print("...waiting for response...")
#recv_data, ADDR = udpCliSock.recvfrom(BUFSIZE)
recv_data, ADDR = client.recvfrom(1024)
if recv_data is not None:
recv_data = recv_data.decode()
print("[%s]: receiving data from server %s:%s :%s" % (ctime(),ADDR[0], ADDR[1], recv_data))
sendData = recv_data
udpCliSock.sendto(sendData.encode(), ADDR)
udpCliSock.close()
SCRIPT 3(Server.py)
from socket import *
from time import ctime
HOST = '192.168.1.103'
PORT = 5005
BUFSIZE = 1024
ADDR = (HOST, PORT)
udpSerSock = socket(AF_INET, SOCK_DGRAM)
udpSerSock.bind(ADDR)
while True:
print("...waiting for message...")
data, ADDR = udpSerSock.recvfrom(BUFSIZE)
print(data.decode)
if data is None:
break
print("[%s]: From Address %s:%s receive data: %s" % (ctime(),ADDR[0],ADDR[1], data.decode()))
udpSerSock.close()
The problem is that, in the Client.py, you are overwriting the address of the server when you receive the datagram from the sensor. Here:
recv_data, ADDR = client.recvfrom(1024)
ADDR starts out with the server's socket address, but this function overwrites that variable with the sensor's socket address. So when you try to send, you're sending it back to the sensor (who of course isn't ever receiving it).
A better method is to connect that socket to the server at the beginning. Then you can just use send instead of sendto since the address won't be changing. Should work after that:
...
udpCliSock = socket(AF_INET, SOCK_DGRAM)
udpCliSock.connect(ADDR) # <<<<<<===============
client = socket(AF_INET, SOCK_DGRAM)
client.bind(CLIENT_ADDR)
while True:
print("...waiting for response...")
recv_data, addr = client.recvfrom(1024)
if recv_data is not None:
recv_data = recv_data.decode()
print("[%s]: receiving data from server %s:%s :%s" % (ctime(),addr[0], addr[1], recv_data))
sendData = recv_data
udpCliSock.send(sendData.encode()) # <<<<<<===============
udpCliSock.close()

how can we use both tcpSerSock.listen(0) and tcpSerSock.send(str.encode(message)) at the same time

my raspberry pi is the server and Im trying to send continuous message from rpi to android while recieving a command from client (android app),i really dont know if this is possible and how to do it is out of my reach and it is not a feedback message here is my code hope you will help me thank you.
import apptopi
from socket import *
from time import ctime
from nanpy import (ArduinoApi, SerialManager)
apptopi.setup()
connection = SerialManager()
a = ArduinoApi(connection = connection)
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
add = 0
add += 1
a = str(add) //**this is a sample that i want to send continously
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(0)
tcpSerSock.send(str.encode(a)) <== i really don't know how to send
continuously
while True:
print 'Waiting for connection'
tcpCliSock,addr = tcpSerSock.accept()
print '...connected from :', addr
try:
while True:
data = ''
data = tcpCliSock.recv(BUFSIZE)
if not data:
break
if data == ctrCmd[0]:
apptopi.forw()
print 'forward'
if data == ctrCmd[1]:
apptopi.back()
print 'backward'
if data == ctrCmd[2]:
apptopi.left()
print 'leftturn'
if data == ctrCmd[3]:
apptopi.right()
print 'rightturn'
if data == ctrCmd[4]:
apptopi.stp()
print 'stop'
except KeyboardInterrupt:
apptopi.close()
GPIO.cleanup()
tcpSerSock.close();
OK one approach is to use the select() function for this. There is information in the documentation about its operation.
As an example I've made a modified version of your program (see below). I don't have a raspberry pi, so that part of the code is commented out, but you can replace it as needed.
The example uses the timeout feature of select() to send "continuous" messages to clients whilst also monitoring them for incoming messages. You can adjust the message contents and timeout to whatever works for you. NB you may also need to respond to client messages, as this code only sends data to clients after a timeout. Make whatever changes you need.
import sys
import socket
import select
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(1)
print 'Waiting for connection'
sendInterval = 1.0 # interval(sec) for sending messages to connected clients
rxset = [tcpSerSock]
txset = []
while 1:
rxfds, txfds, exfds = select.select(rxset, txset, rxset, sendInterval)
if rxfds:
for sock in rxfds:
if sock is tcpSerSock:
# a client is connecting
tcpCliSock, addr = tcpSerSock.accept()
tcpCliSock.setblocking(0)
rxset.append(tcpCliSock)
print '...connected from :', addr
else:
# a client socket has data or has closed the connection
try:
data = sock.recv(BUFSIZE)
if not data:
print "...connection closed by remote end"
rxset.remove(sock)
sock.close()
else:
if data == ctrCmd[0]:
#apptopi.forw()
print 'forward'
if data == ctrCmd[1]:
#apptopi.back()
print 'backward'
if data == ctrCmd[2]:
#apptopi.left()
print 'leftturn'
if data == ctrCmd[3]:
#apptopi.right()
print 'rightturn'
if data == ctrCmd[4]:
#apptopi.stp()
print 'stop'
except:
print "...connection closed by remote end"
rxset.remove(sock)
sock.close()
else:
# timeout - send data to any active client
for sock in rxset:
if sock is not tcpSerSock:
sock.send("Hello!\n")
The simple client program I used to test this is here:
import sys
import socket
import time
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
HOST = '127.0.0.1'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpCliSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpCliSock.connect(ADDR)
time.sleep(1)
for i in range(len(ctrCmd)):
tcpCliSock.send(ctrCmd[i])
time.sleep(1)
data = tcpCliSock.recv(BUFSIZE)
print data
tcpCliSock.close()
Hope this helps, best of luck.

python udp listener not showing on process listening to ports

I have a script which listens to incoming udp packets on port 8087:
IP_ADDRESS = '0.0.0.0'
LISTEN_PORT = 8087
serverSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serverSock.bind((IP_ADDRESS, LISTEN_PORT))
while True:
data, addr = serverSock.recvfrom(1024)
I run the script and can get data if I send packets to it.
When I do sudo netstat -peant | grep ":8087 " to see the process listening on this port, I don't have any results.
When I do sudo netstat -peant | grep ":80 " for example, I do get results of processes listening on this port.
Why is that? something wrong with the udp server code? shouldn't it listen on 8087?
your server listens to the correct port but need proper data handling.
study below code and you will get a good understanding on this.
from socket import *
import string
from time import ctime
HOST = '127.0.0.1'
PORT = 8087
BUFSIZ = 1024
ADDR = (HOST, PORT)
ssock = socket(AF_INET, SOCK_STREAM)
ssock.bind(ADDR)
ssock.listen(5)
try:
while True:
c = 1
print 'Waiting for a connection...'
csock, addr = ssock.accept()
hostname, aliases, addresses = gethostbyaddr(addr[0])
lip, lport = ssock.getsockname()
print '''
Connected ...
Remote Host : %s
Remote host IP : %s
Remort Port : %d
Connected time : %s
Local IP : %s
Local Port : %d \n''' % (hostname , addr[0], addr[1], ctime(), lip, lport)
while True:
data = csock.recv(BUFSIZ)
if data == 'q':
break
elif data == 'shut':
ssock.close()
break
elif data == ' ':
csock.send('Server Responce: <> \n')
print 'srv responces: %d : <>' % c
c += 1
else:
data1 = data.upper()
csock.send('Server Responce: %s \n' % data1)
print 'srv responces: %d : <%s>' % (c, data1)
c += 1
csock.close()
except:
print 'Server socket closed !!!'

TCP vs. UDP socket latency benchmark

I have implemented a small benchmark for socket communication via TCP and UDP in Python. Surprisingly, TCP is almost exactly double as fast as UDP.
To avoid routing effects, server and client are running on the same Unix machine, but on different threads.
Maybe the code is useful. Here is the server code:
import socket
import sys
host = 'localhost'
port = 8888
buffersize = 8
server_address = (host, port)
def start_UDP_server():
socket_UDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket_UDP.bind(server_address)
print("UDP server is running...")
while True:
data, from_address = socket_UDP.recvfrom(buffersize)
if not data: break
socket_UDP.sendto(data, from_address)
socket_UDP.close()
def start_TCP_server():
socket_TCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_TCP.bind(server_address)
socket_TCP.listen(1)
print("TCP server is running...")
while True:
client, client_address = socket_TCP.accept()
while True:
data = client.recv(buffersize)
if not data: break
client.sendall(data)
client.close()
So you can run either start_TCP_server() or start_UDP_server().
On client side the code is:
import socket
import sys
import time
host = 'localhost'
port = 8888
buffersize = 8
server_address = (host, port)
client_address = (host, port+1)
N = 1000000
def benchmark_UDP():
socket_UDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket_UDP.bind(client_address)
print("Benchmark UDP...")
duration = 0.0
for i in range(0, N):
b = bytes("a"*buffersize, "utf-8")
start = time.time()
socket_UDP.sendto(b, server_address)
data, from_address = socket_UDP.recvfrom(buffersize)
duration += time.time() - start
if data != b:
print("Error: Sent and received data are bot the same")
print(duration*pow(10, 6)/N, "µs for UDP")
def benchmark_TCP():
socket_TCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_TCP.connect(server_address)
print("Benchmark TCP...")
duration = 0.0
for i in range(0, N):
b = bytes("a"*buffersize, "utf-8")
start = time.time()
socket_TCP.sendall(b)
data = socket_TCP.recv(buffersize)
duration += time.time() - start
if data != b:
print("Error: Sent and received data are bot the same")
print(duration*pow(10, 6)/N, "µs for TCP")
socket_TCP.close()
Like for the server you can start the benchmark by benchmark_TCP() or benchmark_UDP().
The results are about 25 µs for TCP, and about 54 µs for UDP on Unix and even worse for Windows (about 30 µs for TCP and more than 200 µs for UDP). Why? I would expect a minimal advantage for UDP.
Your TCP socket is connected but your UDP socket is not. This means extra processing for every send/receive on the UDP socket. Call connect on each side for the UDP socket, just like you call connect/accept on the TCP socket.
Programs like iperf do this to measure accurately.

Categories

Resources