ntp client in python - python

I've written a ntp client in python to query a time server and display the time and the program executes but does not give me any results.
I'm using python's 2.7.3 integrated development environment and my OS is Windows 7.
Here is the code:
# File: Ntpclient.py
from socket import AF_INET, SOCK_DGRAM
import sys
import socket
import struct, time
# # Set the socket parameters
host = "pool.ntp.org"
port = 123
buf = 1024
address = (host,port)
msg = 'time'
# reference time (in seconds since 1900-01-01 00:00:00)
TIME1970 = 2208988800L # 1970-01-01 00:00:00
# connect to server
client = socket.socket( AF_INET, SOCK_DGRAM)
client.sendto(msg, address)
msg, address = client.recvfrom( buf )
t = struct.unpack( "!12I", data )[10]
t -= TIME1970
print "\tTime=%s" % time.ctime(t)

Use ntplib:
The following should work on both Python 2 and 3:
import ntplib
from time import ctime
c = ntplib.NTPClient()
response = c.request('pool.ntp.org')
print(ctime(response.tx_time))
Output:
Fri Jul 28 01:30:53 2017

Here is a fix for the above solution, which adds fractions of seconds to the implementation and closes the socket properly. As it's actually just a handful lines of code, I didn't want to add another dependency to my project, though ntplib admittedly is probably the way to go in most cases.
#!/usr/bin/env python
from contextlib import closing
from socket import socket, AF_INET, SOCK_DGRAM
import struct
import time
NTP_PACKET_FORMAT = "!12I"
NTP_DELTA = 2208988800 # 1970-01-01 00:00:00
NTP_QUERY = b'\x1b' + 47 * b'\0'
def ntp_time(host="pool.ntp.org", port=123):
with closing(socket( AF_INET, SOCK_DGRAM)) as s:
s.sendto(NTP_QUERY, (host, port))
msg, address = s.recvfrom(1024)
unpacked = struct.unpack(NTP_PACKET_FORMAT,
msg[0:struct.calcsize(NTP_PACKET_FORMAT)])
return unpacked[10] + float(unpacked[11]) / 2**32 - NTP_DELTA
if __name__ == "__main__":
print time.ctime(ntp_time()).replace(" ", " ")

It should be
msg = '\x1b' + 47 * '\0'
Instead of
msg = 'time'
But as Maksym said you should use ntplib instead.

msg = '\x1b' + 47 * '\0'
.......
t = struct.unpack( "!12I", msg )[10]

Related

Python UDP socket; still receiving data when source is stopped; why?

I am sending 32 bytes packets every 1ms to this socket. I wish to print the data after every 40 ms. And apparently the code does that. But even when I stop sending data, I still continue to see that data is being printed.
Is it holding the data in some cache? or simply the python socket has a huge delay? Why?
The code is as follows:
## Import necessary libraries
import math
import numpy as np
import socket
import struct
import time
from synchrophasor.frame import CommandFrame
from datetime import datetime
## Configure socket for Phasor data ##
UDP_IP = "10.10.114.22"
UDP_PORT = 8208 #UDP phasor values 32 bytes (V,phi,P)
sock_ph = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock_ph.bind((UDP_IP, UDP_PORT))
print("socket bound, waiting for data...")
while True:
raw = sock_ph.recv(32)
#print(raw)
mag = struct.unpack('d', raw[8:16])[0]
# print("mag =",mag,type(mag))
angle = struct.unpack('d', raw[16:24])[0]
# print("angle =",angle,type(angle))
header = struct.unpack('d', raw[0:8])[0]
# print("header =",header,type(header))
phasor = (mag, angle)
Vol_A=raw
VA = float(mag)
phi_A = float(angle)
VB = VA
phi_B = phi_A+(math.pi) * 2 / 3
VC = VA
phi_C = phi_A-(math.pi) * 2 / 3
time.sleep(1/25)
# pmu.send_data(phasors=[(VA,phi_A),(VB,phi_B),(VC,phi_C)],analog=[9.91],digital=[0x0001])
#time.sleep(1/config_rr)
print([(VA,phi_A),(VB,phi_B),(VC,phi_C),datetime.now()])
most programs don't want to discard unread datagrams so most OSs will buffer them for you. your case is somewhat unusual so you'd need to write code to handle this case. I'd change your code to do something like:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('', 8208))
# block until we read an initial packet
raw = s.recv(1024)
s.setblocking(False)
while True:
# unpack
header, mag, angle = struct.unpack('ddd', raw)
# do something with data
print(f'header={header} mag={mag} angle={angle}')
# sleep for some time
time.sleep(1/25)
# discard any packets you've received in the mean time
while True:
try:
raw = s.recv(1024)
except OSError as err:
# OS buffer is empty: we've therefore got the most recent data
if err.errno == socket.EWOULDBLOCK:
break
# something else failing, reraise the error
raise
note that Steffen Ullrich's suggestion of sending the data at the correct rate would be easier, but assumes that you have control over the sending process. the fact that you said "I am sending" suggests you do, and so would likely make a better solution

How to receive and handle multiple TCP stream sockets?

I would like to send the location of a moving point to a server via TCP with the socket module. That point location is updated at each iteration of a for loop and is sent in the form of a tuple (x, y) that has been serialized with pickle dumps methods.
Problem:
On the server side, it seems that I only get to receive the location from the first iteration of that loop. As if all the following updated positions had been skipped or lost in the process.
I can’t say for sure what is the reason behind this behavior but my bet is that I am not correctly setting things on the server side. I suspect the data to be sent entirely but not processed adequately on reception due to some mistakes that I am probably doing with the socket module (I am completely new to the world of network interfaces).
Code:
--client side--
#Python3.7
import socket
import pickle
import math
HOST = "127.0.0.1"
PORT = 12000
den = 20
rad = 100
theta = math.tau / den
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((HOST, PORT)) #connect to server
for step in range(1000):
i = step%den
x = math.cos(i*theta) * rad
y = math.sin(i*theta) * rad
data = pickle.dumps((x, y), protocol=0)
sock.sendall(data)
--server side--
#Jython2.7
import pickle
import socket
HOST = "127.0.0.1"
PORT = 12000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
while True:
connection, address = s.accept()
if connection:
data = connection.recv(4096)
print(pickle.loads(data)) # <-- only print once (first location)
You need to put connection, address = s.accept() outside the while loop otherwise your server will wait for a new connection every time.
You also have an issue with the way your are receiving data. connection.recv(4096) will return any amount of bytes between 0 and 4096 not every time a complete "data" message is received. To handle this you could send a header before sending you json indicating how much data should be received
By adding a header, you will make sure the data messages you are sending will be received properly.
The header in this example is a four bytes int indicating the size of data.
Server
import pickle
import socket
import struct
HEADER_SIZE = 4
HOST = "127.0.0.1"
PORT = 12000
def receive(nb_bytes, conn):
# Ensure that exactly the desired amount of bytes is received
received = bytearray()
while len(received) < nb_bytes:
received += conn.recv(nb_bytes - len(received))
return received
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
connection, address = s.accept()
while True:
# receive header
header = receive(HEADER_SIZE, connection)
data_size = struct.unpack(">i", header)[0]
# receive data
data = receive(data_size, connection)
print(pickle.loads(data))
Client
import socket
import pickle
import math
HEADER_SIZE = 4
HOST = "127.0.0.1"
PORT = 12000
den = 20
rad = 100
theta = math.tau / den
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((HOST, PORT)) #connect to server
for step in range(1000):
i = step%den
x = math.cos(i*theta) * rad
y = math.sin(i*theta) * rad
data = pickle.dumps((x, y), protocol=0)
# compute header by taking the byte representation of the int
header = len(data).to_bytes(HEADER_SIZE, byteorder ='big')
sock.sendall(header + data)
Hope it helps

one python script to open a socket, another to send data over the socket

I am working on an Asterisk AGI and Python 3 integration. I am having trouble with my script and I am thinking it may be because it is running too many at once and the closing of the socket at the end my be causing the issue.
I have a system sending a SIP call to asterisk.
Asterisk then executes the script.
Script opens a TCP socket and sends data closing the socket ending the script.
If I have one call come in at a time or they are staggered the script executes flawlessly. If I have multiple calls come in at once say 5 (which is common in this instance) the socket receiving the data may only process 2 of the fully completed scripts.
I have tried to minimize the script to see if i could get it to execute faster, stripping out things unneeded, removed logging, removed #out lines. The only thing I could do was try and stagger the calls which is not a viable option.
#!/usr/bin/env python3
import serial
import re
from time import sleep
import logging
import logging.handlers
from configparser import ConfigParser
import sys
import asterisk
import asterisk.agi
from asterisk.agi import *
import socket
import os
import sys
config = ConfigParser()
config.read('/var/www/html/config.ini')
LOG_LEVEL = logging.info('LOGGING', 'level')
# Initialize logging
LOGGER = logging.getLogger('axi')
LOGGER.setLevel(logging.INFO)
formatter = logging.Formatter('|%(asctime)s|%(levelname)-8s|%(name)s|%(message)s')
log_file = logging.handlers.TimedRotatingFileHandler('/var/log/axi/input.csv', when='midnight', backupCount=7)
log_file.setLevel(logging.INFO)
log_file.setFormatter(formatter)
LOGGER.addHandler(log_file)
# Only print to console if at DEBUG level
if LOG_LEVEL == 'DEBUG':
log_console = logging.StreamHandler()
log_console.setLevel(logging.INFO)
log_console.formatter(formatter)
LOGGER.addHandler(log_console)
#BAUD = config.get('USB_Settings', 'baudrate')
#PTY = config.get('USB_Settings', 'parity')
#STPB = int(config.get('USB_Settings', 'stopbits'))
#BTSZ = int(config.get('USB_Settings', 'bytesize'))
HOST = config.get('Ethernet_Paging_System', 'IP')
PORT = config.get('Ethernet_Paging_System', 'Port')
agi = AGI()
pin = agi.env['agi_extension']
msg = agi.env['agi_calleridname']
geekspeak = {
"<ESC>": '\\x1b',
"<ETX>": '\\x03',
"<CR>": '\\r',
"<ACK>": '\\x06',
"<NAK>": '\\x15',
"<EOT>": '\\x04',
"<STX>": '\\x02'
}
htmlspeak = {
"&ltESC&gt": '\\x1b',
"&ltETX&gt": '\\x03',
"&ltCR&gt": '\\r',
"&ltACK&gt": '\\x06',
"&ltNAK&gt": '\\x15',
"&ltEOT&gt": '\\x04',
"&ltSTX&gt": '\\x02'
}
def str2geek(string):
geekstr = str(string)
for key, value in geekspeak.items():
if key in geekstr:
geekstr = geekstr.replace(key, value)
return geekstr
def geek2str(string):
sstr = str(string)
for key, value in geekspeak.items():
if value in sstr:
sstr = sstr.replace(value, key)
return sstr
def html2str(string):
hstr = str(string)
for key, value in htmlspeak.items():
if value in hstr:
hstr = hstr.replace(value, key)
return hstr
#Socket setup
s = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_INET, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
s = socket.socket(af, socktype, proto)
except OSError as msg:
s = None
continue
try:
s.connect(sa)
except OSError as msg:
s.close()
s = None
continue
break
if s is None:
LOGGER.info('---Could not open socket')
sys.exit(1)
with s:
s.send(b'\\r')
sleep(0.5)
s.send(b'\\x1bPG1\\r')
strng=(pin)+(msg)
#New Code for Checksum
list_ascii=[ord(i) for i in strng]
#Prints each car decimal value
#print(list_ascii)
b=sum(list_ascii)+31
#Convert sum to 12 bit binary and parse to 4 sections frist 4 middle 4 last 4
h1=(bin(b)[2:].zfill(12)[8:])
h2=(bin(b)[2:].zfill(12)[4:8])
h3=(bin(b)[2:].zfill(12)[0:4])
#Adds 48 decimal value per TAP 1.8
i1=(int(h1, 2)+48)
i2=(int(h2, 2)+48)
i3=(int(h3, 2)+48)
#Gives checksum value
chks=chr(i3)+chr(i2)+chr(i1)
LOGGER.info('---Pin:' + pin + ' - ' + 'Message:' + msg + ' - checksum:' + chks)
s.send('\x02'.encode() + (pin).encode() + '\r'.encode() + msg.encode() + '\r\x03'.encode() + (chks).encode() + '\r'.encode())
resp=str(s.recv(1024))
if resp:
LOGGER.info(html2str(resp))
if '15' in resp:
LOGGER.info('page not accepted')
if resp:
sleep(0.5)
s.send(b'\x04\r')
sleep(0.5)
LOGGER.info('---Page Accepted' + ' - checksum:' + chks)
s.close()
I was hoping to be able to create one script that keeps the TCP socket alive and another will execute on a call to asterisk and send that data either over the socket or to the already running python script and start the process of sending data with variables.
Thank you
Here is how I did it. I got the first script to run on a call to asterisk and the second opens the connection and keeps it open until one side closes.
The asterisk script only runs when a call comes into asterisk and converts an inbound SIP message into a TAP 1.8 message used heavily in the nurse call industry.
The socket script I run as a service opening the connection to send data.
Asterisk Script
#!/usr/bin/env python3
import serial
import re
from time import sleep
import sys
import asterisk
import asterisk.agi
from asterisk.agi import *
import socket
import os
geekspeak = {
"<ESC>": '\\x1b',
"<ETX>": '\\x03',
"<CR>": '\\r',
"<ACK>": '\\x06',
"<NAK>": '\\x15',
"<EOT>": '\\x04',
"<STX>": '\\x02'
}
htmlspeak = {
"&ltESC&gt": '\\x1b',
"&ltETX&gt": '\\x03',
"&ltCR&gt": '\\r',
"&ltACK&gt": '\\x06',
"&ltNAK&gt": '\\x15',
"&ltEOT&gt": '\\x04',
"&ltSTX&gt": '\\x02'
}
def str2geek(string):
geekstr = str(string)
for key, value in geekspeak.items():
if key in geekstr:
geekstr = geekstr.replace(key, value)
return geekstr
def geek2str(string):
sstr = str(string)
for key, value in geekspeak.items():
if value in sstr:
sstr = sstr.replace(value, key)
return sstr
def html2str(string):
hstr = str(string)
for key, value in htmlspeak.items():
if value in hstr:
hstr = hstr.replace(value, key)
return hstr
agi = AGI()
pin = '201' #agi.env['agi_extension']
msg = 'TEST' #agi.env['agi_calleridname']
strng=(pin)+(msg)
#New Code for Checksum
list_ascii=[ord(i) for i in strng]
#Prints each car decimal value
#print(list_ascii)
b=sum(list_ascii)+31
#Convert sum to 12 bit binary and parse to 4 sections frist 4 middle 4 last 4
h1=(bin(b)[2:].zfill(12)[8:])
h2=(bin(b)[2:].zfill(12)[4:8])
h3=(bin(b)[2:].zfill(12)[0:4])
#Adds 48 decimal value per TAP 1.8
i1=(int(h1, 2)+48)
i2=(int(h2, 2)+48)
i3=(int(h3, 2)+48)
#Gives checksum value
chks=chr(i3)+chr(i2)+chr(i1)
#Socket setup
s = None
for res in socket.getaddrinfo("localhost", 9988, socket.AF_INET, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
s = socket.socket(af, socktype, proto)
except OSError as msg:
s = None
continue
try:
s.connect(sa)
except OSError as msg:
s.close()
s = None
continue
break
if s is None:
sys.exit(1)
with s:
s.send('\x02'.encode() + (pin).encode() + '\r'.encode() + msg.encode() + '\r\x03'.encode() + (chks).encode() + '\r'.encode())
s.close()
Socket Script
#!/usr/bin/env python3
import serial
import re
from time import sleep
import logging
import logging.handlers
from configparser import ConfigParser
import socket
import os
import sys
config = ConfigParser()
config.read('/var/www/html/config.ini')
LOG_LEVEL = logging.info('LOGGING', 'level')
# Initialize logging
LOGGER = logging.getLogger('axi')
LOGGER.setLevel(logging.INFO)
formatter = logging.Formatter('|%(asctime)s|%(levelname)-8s|%(name)s|%(message)s')
log_file = logging.handlers.TimedRotatingFileHandler('/var/log/axi/input.csv', when='midnight', backupCount=7)
log_file.setLevel(logging.INFO)
log_file.setFormatter(formatter)
LOGGER.addHandler(log_file)
# Only print to console if at DEBUG level
if LOG_LEVEL == 'DEBUG':
log_console = logging.StreamHandler()
log_console.setLevel(logging.INFO)
log_console.formatter(formatter)
LOGGER.addHandler(log_console)
HOST = config.get('Ethernet_Paging_System', 'IP')
PORT = config.get('Ethernet_Paging_System', 'Port')
#Socket setup
s2 = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_INET, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
s2 = socket.socket(af, socktype, proto)
except OSError as msg:
s2 = None
continue
try:
s2.connect(sa)
except OSError as msg:
s2.close()
s2 = None
continue
break
if s2 is None:
LOGGER.info('---Could not open socket')
sys.exit(1)
#listening Socket
s3 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s3.bind(("localhost", 9988))
s3.listen(1)
while True:
conn, addr = s3.accept()
data = conn.recv(1024)
if data:
#with s2:
s2.send(b'\\r')
sleep(0.5)
s2.send(b'\\x1bPG1\\r')
LOGGER.info(data)
s2.send(data)
resp=str(s2.recv(1024))
if resp:
# LOGGER.info(html2str(resp))
if '15' in resp:
LOGGER.info('page not accepted')
if resp:
s2.send(b'\x04\r')
LOGGER.info('---Page Accepted')

Time server network

I want to get the time using the Time protocol found in RFC 868.
I am using python to do that.
here is my code:
import socket
server = "time.nist.gov"
port = 37
receive_buffer_size = 4096
mysocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
mysocket.connect((server, port))
response_string = mysocket.recv( receive_buffer_size )
mysocket.close
print response_string
I'm supposed to get a 32 bit number, but i'm getting garbage!
any idea where is the problem?
I believe you got the RAW DATA
Try this:
data, = struct.unpack('!I', response_string)
print "%x " %data

Python server-client relationship over network problems

I wrote a program for my networking class that measures upload and download speeds by sending a file over a socket and timing the transfer, and I used Python. The problem I'm having is that the server and client can talk just fine when running on the same machine, but as soon as I put the server program on another machine on my network, no file transfer happens. They talk to each other (Client says "connected to server" and server says "connection from xxx.xxx.xxx.xxx") but the file transfer size and speed are shown as 0 and 0.
Here's the server code:
import util
import socket
import os
import shutil
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ""
port = 12345
f = open("receivedfromclient.txt", "r+")
print "Waiting for clients..."
s.bind((host, port))
s.listen(5)
c, addr = s.accept()
print "Client connected:", addr
start = time.clock()
msg = c.recv(257024)
stop = time.clock()
duration = stop-start
f.write(str(msg))
b = os.path.getsize("receivedfromclient.txt")
print "File size = ", b, "bits"
print "Time to transfer from client = ", duration, " seconds"
bw = (b/duration)/1048576
print "The upload bit rate is ", bw, "Mpbs"
f.close()
shutil.copy("receivedfromclient.txt", "sendtoclient.txt")
f.open("sendtoclient.txt")
c.send(f.read())
f.close()
c.close()
s.close()
and the client code is similar:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = raw_input("Please enter host address: ")#socket.gethostname()
port = 12345
sendfile = raw_input("Please enter name of file to transfer: ")
f = open(sendfile,"rb")
g = open("receivedfromserver.txt","w")
print "Connecting to ", host, port
s.connect((host, port))
s.send(f.read())
and so on. Can anybody tell me what I'm doing wrong here?
Hmm - there are at least some problems:
The major one is, that IMHO it is not clear what you really want to do.
Here is your code with some remarks:
# import util <-- NOT NEEDED
import socket
import os
import shutil
import time # <-- Added
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ""
port = 12345
f = open("receivedfromclient.txt", "r+")
print "Waiting for clients..."
s.bind((host, port))
s.listen(5)
c, addr = s.accept() # <-- FORGOTTEN ()
print "Client connected:", addr
start = time.clock()
msg = c.recv(257024) # <-- You need some loop here to get the whole file
stop = time.clock()
duration = stop-start
f.write(str(msg))
b = os.path.getsize("receivedfromclient.txt") # <-- = instead of .
print "File size = ", b, "bits"
print "Time to transfer from client = ", duration, " seconds"
bw = (b/duration)/1048576
print "The upload bit rate is ", bw, "Mpbs"
f.close()
shutil.copy("receivedfromclient.txt", "sendtoclient.txt")
f.open("sendtoclient.txt")
c.send(f.read())
f.close()
c.close()
s.close()
One problem here is, that start is in mostly all cases equal to stop - so you get a Division By Zero error in (b/duration).
In the client part at least a import socket is missing; the g is not needed at all.
Please explain further, what you want to do.
If you want to transfer files, there are a lot of ways to do (sftp, rsync, nc, ...).

Categories

Resources