Linux Kernel offers a few ways to get timestamps for received (SO_TIMESTAMP, SO_TIMESTAMPNS, SO_TIMESTAMPING) or sent (SO_TIMESTAMPING) packets.
Kernel Doc: https://www.kernel.org/doc/Documentation/networking/timestamping.txt
Is there a way I can use that with Python? I don't see any SO_TIMESTAMP constant inside the Python sources. Tried 3.6.2 and GitHub master branch.
Right now, I can only use SIOCGSTAMP that gives me the timestamp of the last received packet and nothing seems available for sent packet timestamp.
Finally, I have been able to get the SO_TIMESTAMPNS value like this:
SO_TIMESTAMPNS = 35
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(3))
s.setsockopt(socket.SOL_SOCKET, SO_TIMESTAMPNS, 1)
raw_data, ancdata, flags, address = s.recvmsg(65535, 1024)
ancdata[0][2] is the hardware timestamp as a timespec(ulong, ulong).
Does work on Linux but not on Mac OS X. Not tested on Windows.
complete code, send and receive using python3
import struct
import time
import select
import socket
import sys
if(len(sys.argv)!=2):
print("usage: ",sys.argv[0]," <send|receive>")
sys.exit()
print(sys.argv[1]);
if(sys.argv[1]=='send'):
MESSAGE = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
s.connect(('localhost', 10000))
s.send(MESSAGE)
time.sleep(0.0001)
#time.sleep(5)
s.send(MESSAGE)
s.close()
else:
SO_TIMESTAMPNS = 35
#s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(3))
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(0)
server.setsockopt(socket.SOL_SOCKET, SO_TIMESTAMPNS, 1)
server.bind(('localhost', 10000))
server.listen(5)
inputs = [ server ]
message_queues = {}
outputs = []
while inputs:
print('\nwaiting for the next event')
readable, writable, exceptional = select.select(inputs, outputs, inputs)
for s in readable:
if s is server:
connection, client_address = s.accept()
print('new connection from', client_address)
connection.setblocking(0)
inputs.append(connection)
else:
raw_data, ancdata, flags, address = s.recvmsg(65535, 1024)
print('received ', raw_data, '-',ancdata,'-',flags,'-',address)
if(len(ancdata)>0):
#print(len(ancdata),len(ancdata[0]),ancdata[0][0],ancdata[0][1],ancdata[0][2])
#print('ancdata[0][2]:',type(ancdata[0][2])," - ",ancdata[0][2], " - ",len(ancdata[0][2]));
for i in ancdata:
print('ancdata: (cmsg_level, cmsg_type, cmsg_data)=(',i[0],",",i[1],", (",len(i[2]),") ",i[2],")");
if(i[0]!=socket.SOL_SOCKET or i[1]!=SO_TIMESTAMPNS):
continue
tmp=(struct.unpack("iiii",i[2]))
timestamp = tmp[0] + tmp[2]*1e-10
print("SCM_TIMESTAMPNS,", tmp, ", timestamp=",timestamp)
if(not raw_data):
print('closing after reading no data')
# Stop listening for input on the connection
if s in outputs:
outputs.remove(s)
inputs.remove(s)
s.close()
Related
I am using my server code on a raspberry pi and my client code on my laptop. I also off the firewall on my computer. After connecting to the server, I manage to run the loop for once from the client side by keying the word "data" and when I keyed in another command it just came out of the loop. If i key in Quit it says that it have an OS error98 address already in used. May I know how to keep the loop on going ? Below I is my client.py and server.py code.
Server.py code:
import socket
import numpy as np
import encodings
HOST = '192.168.1.65'
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
def random_data(): # ANY DATA YOU WANT TO SEND WRITE YOUR SENSOR CODE HERE
x1 = np.random.randint(0, 55, None) # Dummy temperature
y1 = np.random.randint(0, 45, None) # Dummy humidigy
my_sensor = "{},{}".format(x1,y1)
return my_sensor # return data seperated by comma
def my_server():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
print("Server Started waiting for client to connect ")
s.bind((HOST, PORT))
s.listen(5)
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024).decode('utf-8')
if str(data) == "Data":
print("Ok Sending data ")
my_data = random_data()
x_encoded_data = my_data.encode('utf-8')
conn.sendall(x_encoded_data)
elif str(data) == "Quit":
print("shutting down server ")
break
else:
pass
if __name__ == '__main__':
while 1:
my_server()
Client.py Code:
import socket
import threading
import time
HOST = '192.168.1.65' # The server's hostname or IP address
PORT = 65432 # The port used by the server
def process_data_from_server(x):
x1, y1 = x.split(",")
return x1,y1
def my_client():
threading.Timer(11, my_client).start()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
my = input("Enter command ")
my_inp = my.encode('utf-8')
s.sendall(my_inp)
data = s.recv(1024).decode('utf-8')
x_temperature,y_humidity = process_data_from_server(data)
print("Temperature {}".format(x_temperature))
print("Humidity {}".format(y_humidity))
s.close()
time.sleep(5)
if __name__ == "__main__":
while 1:
my_client()
address already used
you need to use socket.setsockopt to set socket.SO_REUSEADDR in i think both client and server.py
def my_server():
# with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print("Server Started waiting for client to connect ")
s.bind((HOST, PORT))
s.listen(5)
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024).decode('utf-8')
if str(data) == "Data":
...
I have a server and I need it to receive multiple connections and messages.
The server receives new connections without problems but it doesn't get multiple messages from one connection.
import socket
import select
HEADER_LENGTH = 1024
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
server_socket.bind((HOST, PORT))
except socket.error as e:
print(str(e))
print("Server is connected")
server_socket.listen(5)
sockets_list = [server_socket]
clients = {}
print("Server is listening")
def receive_message(conn):
try:
data = conn.recv(HEADER_LENGTH)
if not len(data):
return False
strdata = data.decode('utf-8')
print(strdata)
return strdata
except Exception as e:
print(e)
return False
def handle_client():
conn, addr = server_socket.accept()
print(f"Accepted new connection from {addr[0]}:{addr[1]}")
sockets_list.append(conn)
while True:
read_sockets, _, exception_sockets = select.select(sockets_list, [], [], 0)
for i in read_sockets:
if i == server_socket:
handle_client()
else:
print("received message")
message = receive_message(i)
if message is False:
sockets_list.remove(i)
try:
del clients[i]
except KeyError:
pass
continue
if message is not None:
clients[i] = message
if message is not None:
for client_socket in clients:
if client_socket != i:
client_socket.send(str.encode(message))
print("sent to all players")
What happens it that after receiving the first message, the server stops receiving messages from that connection.
And of course there is a lot more code but I showed you the relevant code.
I'll be very happy if someone helps me with that, I've surfed the web so much but haven't seen a solution for my problem.
updates:
I've tried to put socket.close() on my client side(written in Java) and then server gets maximum 2 messages and the problems with it are:
1. The server gets maximum 2 messages.
2. the connection changes(I need that the connection will stay static if possible)
try this code block
#-*- coding:utf-8 -*-
import socket
import sys
#get machine ip address
server_ip = socket.gethostbyname(socket.gethostname())
#create socket object
s = socket.socket()
#define port number
port = 6666
#bind ip and port to server
s.bind((server_ip,port))
#now waiting for clinet to connect
s.listen(5)
print("Enter this ip to connect your clinet")
print(server_ip)
clients = []
flag = True
recv_data = ""
if not clients:
c, addr = s.accept()
print("this is c ",c," this is Addr ",addr)
clients.append(c)
recv_data = c.recv(1024)
print(recv_data.decode("utf-8"))
if flag == True:
while recv_data.decode("utf-8") != "EX":
recv_data = c.recv(1024)
recv_data.decode("utf-8")
if recv_data.decode("utf-8") == "EX":
s.close()
print("check false")
break
s.close()
I have a listener on a tcp localhost:
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
def client_socket():
while 1:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP,TCP_PORT))
s.listen(1)
while 1:
print 'Listening for client...'
conn, addr = s.accept()
print 'Connection address:', addr
data = conn.recv(BUFFER_SIZE)
if data == ";" :
conn.close()
print "Received all the data"
i=0
for x in param:
print x
#break
elif data:
print "received data: ", data
param.insert(i,data)
i+=1
#print "End of transmission"
s.close()
I am trying to send a JSON object to the same port on the local host:
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
def json_message(direction):
local_ip = socket.gethostbyname(socket.gethostname())
data = {
'sender' : local_ip,
'instruction' : direction
}
json_data = json.dumps(data, sort_keys=False, indent=2)
print("data %s" % json_data)
send_message(json_data)
return json_data
def send_message(data):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(data)
data = s.recv(1024)
print('Received', repr(data))
However, I get a socket error:
socket.error: [Errno 98] Address already in use
What am I doing wrong? Will this work or do I need to serialize the JSON object?
There are a few problems with your code, but the one that will likely address your issue is setting the SO_REUSEADDR socket option with:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
after you create the socket (with socket.socket(...) but before you attempt to bind to an address (with s.bind().
In terms of other things, the two "halves" of the code are pretty inconsistent -- like you copied and pasted code from two different places and tried to use them?
(One uses a context manager and Python 3 print syntax while the other uses Python 2 print syntax...)
But I've written enough socket programs that I can decipher pretty much anything, so here's a working version of your code (with some pretty suboptimal parameters e.g. a buffer size of 1, but how else would you expect to catch a single ;?)
Server:
import socket
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
BUFFER_SIZE = 1
def server_socket():
data = []
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST,PORT))
s.listen()
while 1: # Accept connections from multiple clients
print('Listening for client...')
conn, addr = s.accept()
print('Connection address:', addr)
while 1: # Accept multiple messages from each client
buffer = conn.recv(BUFFER_SIZE)
buffer = buffer.decode()
if buffer == ";":
conn.close()
print("Received all the data")
for x in data:
print(x)
break
elif buffer:
print("received data: ", buffer)
data.append(buffer)
else:
break
server_socket()
Client:
import socket
import json
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
def json_message(direction):
local_ip = socket.gethostbyname(socket.gethostname())
data = {
'sender': local_ip,
'instruction': direction
}
json_data = json.dumps(data, sort_keys=False, indent=2)
print("data %s" % json_data)
send_message(json_data + ";")
return json_data
def send_message(data):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(data.encode())
data = s.recv(1024)
print('Received', repr(data))
json_message("SOME_DIRECTION")
this is my server:
import socket
for port in range(33,128):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('0.0.0.0', port))
while True:
(client_name, client_adress) = server_socket.recvfrom(1024)
print chr(port)
server_socket.close()
this is my client:
import socket
message = raw_input("Enter a message: ")
for letter in message:
my_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
my_socket.sendto("", ('127.0.0.1', ord(letter)))
(data, remote_adress) = my_socket.recvfrom(1024)
my_socket.close()
print 'The server sent: ' + data
I'm not very good in python, but I think you should save your sockets to list inside for and then use select function in infinite loop outside for
import socket
import select
sockets = []
for port in range(33,128):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('0.0.0.0', port))
sockets.append(server_socket)
empty = []
while True:
readable, writable, exceptional = select.select(sockets, empty, empty)
for s in readable:
(client_data, client_address) = s.recvfrom(1024)
print client_address, client_data
for s in sockets:
s.close()
I am writing a simple python tcp code to send over a wav file however I seem to be getting stuck. can someone explain why my code is not working correctly?
Server Code
import socket, time
import scipy.io.wavfile
import numpy as np
def Main():
host = ''
port = 3333
MAX = 65535
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(1)
print "Listening on port..." + str(port)
c, addr = s.accept()
print "Connection from: " + str(addr)
wavFile = np.array([],dtype='int16')
i = 0
while True:
data = c.recvfrom(MAX)
if not data:
break
# print ++i
# wavfile = np.append(wavfile,data)
print data
timestr = time.strftime("%y%m%d-%h%m%s")
print timestr
# wavF = open(timestr + ".wav", "rw+")
scipy.io.wavfile.write(timestr + ".wav",44100, data)
c.close()
if __name__ == '__main__':
Main()
Client Code
host, port = "", 3333
import sys , socket
import scipy.io.wavfile
# create a tcp/ip socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# connect the socket to the port where the server is listening
server_address = (host, port)
print >>sys.stderr, 'connecting to %s port %s' % server_address
input_data = scipy.io.wavfile.read('Voice 005.wav',)
audio = input_data[1]
sock.connect(server_address)
print 'have connected'
try:
# send data
sock.sendall(audio)
print "sent" + str(audio)
sock.close()
except:
print('something failed sending data')
finally:
print >>sys.stderr, 'closing socket'
print "done sending"
sock.close()
Please help someone, I want to send an audio file to my embedded device with tcp since it crucial data to be processed on the embedded device.
Not sure why you go to the trouble of using scipy and numpy for this, since you can just use the array module to create binary arrays that will hold the wave file. Can you adapt and use the simple client/server example below?
(Note: I've copy/pasted a small Windows sound file called 'tada.wav' to the same folder to use with the test scripts.)
Code for the server script:
import socket
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
print('Listening...')
conn, addr = s.accept()
print('Connected by', addr)
outfile = open("newfile.wav", 'ab')
while True:
data = conn.recv(1024)
if not data: break
outfile.write(data)
conn.close()
outfile.close()
print ("Completed.")
Code for the client:
from array import array
from os import stat
import socket
arr = array('B') # create binary array to hold the wave file
result = stat("tada.wav") # sample file is in the same folder
f = open("tada.wav", 'rb')
arr.fromfile(f, result.st_size) # using file size as the array length
print("Length of data: " + str(len(arr)))
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.send(arr)
print('Finished sending...')
s.close()
print('done.')
This works for me (though only tested by running both on localhost) and I end up with a second wave file that's an exact copy of the one sent by the client through the socket.