Implementing reliability in UDP (python) - python-3.x

I have written the code for transferring an audio file from client to server using udp (python).
Now I am required to introduce reliability in the codes of UDP. The instructions are given as:
"You will be required to implement following to make UDP reliable:
(a) Sequence and acknowledge numbers
(b) Re-transmission (selective repeat)
(c) Window size of 5-10 UDP segments (stop n wait)
(d) Re ordering on receiver side "
THE SENDER THAT IS CLIENT CODE IS GIVEN BELOW
from socket import *
import time
# Assigning server IP and server port
serverName = "127.0.0.1"
serverPort = 5000
# Setting buffer length
buffer_length = 500
# Assigning the audio file a name
my_audio_file = r"C:\Users\mali.bee17seecs\PycharmProjects\TestProject\Aye_Rah-e-Haq_Ke_Shaheedo.mp3"
clientSocket = socket(AF_INET, SOCK_DGRAM)
# Opening the audio file
f = open(my_audio_file, "rb")
# Reading the buffer length in data
data = f.read(buffer_length)
# While loop for the transfer of file
while data:
if clientSocket.sendto(data, (serverName, serverPort)):
data = f.read(buffer_length)
time.sleep(0.02) # waiting for 0.02 seconds
clientSocket.close()
f.close()
print("File has been Transferred")
THE RECEIVER THAT IS SERVER CODE IS GIVEN BELOW
from socket import *
import select
# Assigning server IP and server port
serverName = "127.0.0.1"
serverPort = 5000
# Setting timeout
timeout = 3
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind((serverName, serverPort))
# While loop for the receiving of file
while True:
data, serverAddress = serverSocket.recvfrom(1024)
if data:
file = open(r"C:\Users\mali.bee17seecs\PycharmProjects\TestProject\Aye_Rah-e-Haq_Ke_Shaheedo.mp3",
"wb")
while True:
ready = select.select([serverSocket], [], [], timeout)
if ready[0]:
data, serverAddress = serverSocket.recvfrom(500)
file.write(data)
else:
file.close()
print("File has been Received")
break

Before answer each request, you should know that we build a reliable UDP by adding some specific infomation before the real content, which you can think as a application layer head. We use them to do some control or collect infomation like TCP does in traffic layer by the head part. It may look like below:
struct Head {
int seq;
int size;
}
(a) Sequence and acknowledge numbers
If you're familar with TCP, it is not hard. You can set seq and when the other side receive it, the controller will judge it and to check if we need to do b/d.
(b) Re-transmission (selective repeat) & (d) Reordering on receiver side
They are familiar to realise, using GBN/ARQ/SACK algorithm to do retransmission, using some simple algorithm like sorting to do reording.
(c) Window size of 5-10 UDP segments (stop n wait)
This part need to do some thing like traffic control that TCP does. I don't how complex you want to do, it's can be really complex or simple, it depends on you.

Related

My if & elif not working on sockets (python 3)

I tried to create a server that receives commands from the client
And to identify which command the client wrote I used if & elif
But when I run the program and write a command from the client, only the first command works (the command on the if) and if I try another command (from elif & else)
The system just doesn't respond (like she's waiting for something)
The Server Code:
import socket
import time
import random as rd
soc = socket.socket()
soc.bind(("127.0.0.1", 7777))
soc.listen(5)
(client_socket, address) = soc.accept()
if(client_socket.recv(4) == b"TIME"):
client_socket.send(time.ctime().encode())
elif(client_socket.recv(4) == b"NAME"):
client_socket.send(b"My name is Test Server!")
elif(client_socket.recv(4) == b"RAND"):
client_socket.send(str(rd.randint(1,10)).encode())
elif(client_socket.recv(4) == b"EXIT"):
client_socket.close()
else:
client_socket.send(b"I don't know what your command means")
soc.close()
The Client Code:
import socket
soc = socket.socket()
soc.connect(("127.0.0.1", 7777))
client_command_to_the_server = input("""
These are the options you can request from the server:
TIME --> Get the current time
NAME --> Get the sevrer name
RAND --> Get a Random int
EXIT --> Stop the connect with the server
""").encode()
soc.send(client_command_to_the_server)
print(soc.recv(1024))
soc.close()
if(client_socket.recv(4) == b"TIME"):
client_socket.send(time.ctime().encode())
This will check the first 4 byte received from the server
elif(client_socket.recv(4) == b"NAME"):
client_socket.send(b"My name is Test Server!")
This will check the next 4 bytes received from the server. Contrary to what you assume it will not check the first bytes again since you called recv to read more bytes. If there are no more bytes (likely, since the first 4 bytes are already read) it will simply wait. Instead of calling recv for each comparison you should call recv once and then compare the result against the various strings.
Apart from that: recv will only return up to the given number of bytes. It might also return less.

Sending Bytes properly to client

In Python, I am trying to build a simple server/client application that sends video bytes to the client.
I have been trying to figure this out for months.
The server is listening to a connection, and is receiving this much data every second, length of 1316
for example:
data = sock_reciever.recv(16000000)
If I print data, I get this:
b'G\x05\x14\x1e\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffG\x05\x14\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffG\x05\x14\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffG\x05\x14\x11\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffG\x05\x14\x12\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffG\x05\x14\x13\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffG\x05\x17\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
As this comes in, I can send it back out via sock_sender.sendto(data, (SENDMCAST_GRP, SENDMCAST_PORT)), and watch the video in VLC player.
Ultimately, I want to take this data and send it to the client through the socket via conn.send(data).
However, on the client side, I believe data is coming in in the wrong order.
I've compared the data between server and client and it appears to be the same, but it builds up on the client side, which might be causing some sort of overflow.
On the client side, I take the data coming in with data = sock_reciever.recv(16000000) and send it back out via sock_sender.sendto(data, (SENDMCAST_GRP, SENDMCAST_PORT)).
But I do not get the same results on the client side, as on the server side.
How do I add headers to this data to ensure it arrives to the client in sequential order?
If possible, please explain this to me like you would explain what oxygen is to a fish.
Which Sockets I Am Using
I am trying to use TCP sockets between server and client. I thought using a stream socket would be more reliable, but I might be wrong, the only reason being that I would like to do a reverse connection, so that the client connects to the server and then receives data.
I am also using sock_sender.sendto(data, (SENDMCAST_GRP, SENDMCAST_PORT)) just to relay the incoming data on the client side, it is not the actual connection between server and client.
The socket used for the communication between server/client
is called sock_client.
This is the server-side code:
sock_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# recieves connection from client
conn, address = sock_client.accept()
# sends data to client
conn.send(data)
Client Side is set up like so:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
data = s.recv(2400000)
Then the data is just relayed back out for use with other applications via sock_sender.sendto(data, (SENDMCAST_GRP, SENDMCAST_PORT)).
I need to ensure the data between the client/server socket connection is accurate and complete.
Let me explain it a little bit. The video can be sent in the form of bytes with the aid of struct. It is part of the python standard library string services.
It interprets strings as packed binary data and performs conversions between Python values and C structs represented as Python strings. This is helpful handling binary data in files, socket network connections and other sources. In server.py, the frame matrix is pickled dump as a string in variable a and then used struct.pack to add a reference payloadsize (for the string in a). The payload_size is attached using + to the a and then .sendall sends the whole frame. To simply explain it, lets suppose our frame is just 3x3 matrix:
frame=np.array([[1,2,3],[4,5,6],[7,8,9]])
a = pickle.dumps(frame)
The pickled form of frame is shown below as a string:
b'\x80\x03cnumpy.core.multiarray\n_reconstruct\nq\x00cnumpy\nndarray\nq\
x01K\x00\x85q\x02C\x01bq\x03\x87q\x04Rq\x05(K\x01K\x03K\x03\x86q\x06cnumpy
\ndtype\nq\x07X\x02\x00\x00\x00i4q\x08K\x00K\x01\x87q\tRq\n(K\x03X\x01\x00
\x00\x00
Here payload_size: len(a) is 193 and its string representation in a 4 byte 'L' format is b'\xc1\x00\x00\x00'.
Then, message = struct.pack("L", len(a))+a
b'\xc1\x00\x00\x00\x80\x03cnumpy.core.multiarray\n_reconstruct\nq\x00cnumpy\nndarray\nq\
x01K\x00\x85q\x02C\x01bq\x03\x87q\x04Rq\x05(K\x01K\x03K\x03\x86q\x06cnumpy
\ndtype\nq\x07X\x02\x00\x00\x00i4q\x08K\x00K\x01\x87q\tRq\n(K\x03X\x01\x00
\x00\x00
And now the message also contains the payload_size infront of the data. The len(message) = 197.
In client.py the s.recv(4096) means at the most 4096 bytes will be received through a blocking call.
The data is appended to the string in 4096 bytes per packet. The rest of the part is quite obvious.
For reference working versions of server.py and client.py are below. First run the server.py and then in another command window run client.py. The transmitted and received frames will be displayed. You can increase the number of maximum bytes. I hope this solves your problem!
server.py
import socket,cv2,pickle
import struct
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 9999
serversocket.bind((host, port))
serversocket.listen(5)
while True:
clientsocket,addr = serversocket.accept()
print("Got a connection from %s" % str(addr))
if clientsocket:
vid = cv2.VideoCapture(0)
while(vid.isOpened()):
img, frame = vid.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
print(frame)
a = pickle.dumps(frame)
message =struct.pack("L", len(a))+a
clientsocket.sendall(message)
cv2.imshow('Transmitted',frame)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
clientsocket.close()
client.py
import socket,cv2,pickle
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 9999
s.connect((host, port))
data = b""
payload_size = struct.calcsize("L")
while True:
while len(data) < payload_size:
packet= s.recv(4096)
if not packet: break
data += packet
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("L", packed_msg_size)[0]
while len(data) < msg_size:
data += s.recv(4096)
frame_data = data[:msg_size]
data = data[msg_size:]
frame=pickle.loads(frame_data)
cv2.imshow('Received',frame)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
s.close()

Close a HTTP Proxy Server

I have a little problem with my code, I'm doing a HTTP Proxy Server and I send it a random number of HTTP Request and I want that my program close when I stop of send.
I think the problem is in the accept because the program still working always
I tried to put a recv after the accept for checking if there if empty but the program does't arrive there
My code is the following
from socket import *
from _thread import *
MAX_DATA_RECV = 4096 # max number of bytes we receive at once
def start(port_5, my_port):
s=socket(AF_INET, SOCK_STREAM)
s.bind(('', my_port))
s.listen(1)
while 1:
try:
conn, client_addr = s.accept()
except KeyboardInterrupt:
print('\nProgram closed. Interrupted by the user')
exit()
proxy_thread(conn, client_addr)
s.close()
def proxy_thread(conn, client_addr):
# get the request from browser
request = conn.recv(MAX_DATA_RECV).decode('utf-8')
# parse the first line
first_line = request.split('n')[0]
# get url
url = first_line.split(' ')[1]
# find the webserver and port
http_pos = url.find("://") # find pos of ://
if (http_pos==-1):
temp = url
else:
temp = url[(http_pos+3):] # get the rest of url
port_pos = temp.find(":") # find the port pos (if any)
# find end of web server
webserver_pos = temp.find("/")
if webserver_pos == -1:
webserver_pos = len(temp)
webserver = ""
port = -1
if (port_pos==-1 or webserver_pos < port_pos): # default port
port = 80
webserver = temp[:webserver_pos]
else: # specific port
port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1])
webserver = temp[:port_pos]
print("Connect to:", webserver, port)
# create a socket to connect to the web server
s = socket(AF_INET, SOCK_STREAM)
s.connect((webserver, port))
s.send(request.encode()) # send request to webserver
print(temp)
while 1:
# receive data from web server
data = s.recv(MAX_DATA_RECV)
if (len(data) > 0):
# send to browser
conn.send(data)
else:
break
s.close()
conn.close()
If someone is able to help me, thanks in advance
I want that my program close when I stop of send
At the network level there is no implicit indicator that the other side will not send anymore. If all requests would be done through a single TCP connection then the end of the connection might be treated as such an indicator. But you are using a new TCP connection for every request so you need to define your own condition(s) how the server should determine that the client will not send anymore.
This could for example a timeout, i.e. if the client has not sent any more request for 20 seconds then the client is treated as dead. Or it might be a special message by the client to signal the end - in which case your code needs to explicitly look for this message.

Python36 and sockets

So I'm connected to an IRC chat using socket.connec
I log in by passing my variables via socket.send
The log in is successful and then I sit in a while true loop using
Socket.recv(1024)
If I just continually print the response everything looks fine, but let's say I want to add to the end of the string... I noticed that socket.recv doesn't always get the full message (only grabs up to 1024 as expected) and the remainder of the message is in the next iteration of the loop.
This makes its it impossible to process the feedback line by line.
Is there a better way to constantly read the data without it getting trunked? Is it possible to figure out the size of the response before receiving it so the buffer can be set dynamically?
TCP is a stream-based protocol. Buffer the bytes received and only extract complete messages from the stream.
For complete lines, look for newline characters in the buffer.
Example server:
import socket
class Client:
def __init__(self,socket):
self.socket = socket
self.buffer = b''
def getline(self):
# if there is no complete line in buffer,
# add to buffer until there is one.
while b'\n' not in self.buffer:
data = self.socket.recv(1024)
if not data:
# socket was closed
return ''
self.buffer += data
# break the buffer on the first newline.
# note: partition(n) return "left of n","n","right of n"
line,newline,self.buffer = self.buffer.partition(b'\n')
return line + newline
srv = socket.socket()
srv.bind(('',5000))
srv.listen(1)
conn,where = srv.accept()
client = Client(conn)
print(f'Client connected on {where}')
while True:
line = client.getline()
if not line:
break
print(line)
Example client:
s=socket()
s.connect(('127.0.0.1',5000))
s.sendall(b'line one\nline two\nline three\nincomplete')
s.close()
Output on server:
Client connected on ('127.0.0.1', 2667)
b'line one\n'
b'line two\n'
b'line three\n'

How do I manage TCP Client read/write overlap issues?

I have a TCP client communicating with a LabVIEW GUI.
My program calls connect() at the start and disconnect() at the end. It will call passCommand(x) to read or write data to the LabVIEW GUI. However, in some cases, I have multiple threads which may be calling passCommand() and somehow the return data will get mixed up.
For example, in the main thread I will ask for the voltage, which should be a number between 300 and 400. In a different thread I will ask for the temperature, which should be a number from 0-100. The voltage will be returned as 25, while the temperature will get 250.
Is this a known issue with TCP communication and threading? Is there a way to solve this such as implementing a queue or unique id or something?
import socket as _socket
# get python major version as integer
from sys import version as pythonVersion
pythonVersionMajor = int(pythonVersion[0])
_serverHost = 'localhost'
_serverPort = 50007
isConnected = 0
_sockobj = None
_error_string = "error:"
def connect():
'opens a connection to LabVIEW Server'
global _sockobj, isConnected
_sockobj = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM) # create socket
_sockobj.connect((_serverHost, _serverPort)) # connect to LV
isConnected = 1
def disconnect():
'closes the connection to LabVIEW Server'
global isConnected
_sockobj.close() # close socket
isConnected = 0
def passCommand(command):
'passes a command to LabVIEW Server'
## We prepend the command length (8 char long) to the message and send it to LV
# Compute message length and pad with 0 on the left if required
commandSize=str(len(command)).rjust(8,'0')
# Prepend msg size to msg
completeCommand=commandSize+command
# python 3 requires data to be encoded
if (pythonVersionMajor >= 3):
completeCommand = str.encode(completeCommand)
# Send complete command
_sockobj.send(completeCommand)
data = _sockobj.recv(11565536)
# python 3 requires data to be decoded
if (pythonVersionMajor >= 3):
data = bytes.decode(data)
if data.rfind(_error_string) == 0:
error = True
data = data[len(_error_string):] # get data after "error:" string
else:
error = False
execString = "lvdata = " + data
exec(execString, globals())
if error:
raise _LabVIEWError(lvdata)
else:
return lvdata
class _Error(Exception):
"""Base class for exceptions in this module."""
pass
class _LabVIEWError(_Error):
"""Exception raised for errors generated in LabVIEW.
Attributes:
code -- LabVIEW Error Code
source -- location of the error
message -- explanation of the error
"""
def __init__(self, error):
self.code = error[0]
self.source = error[1]
self.message = error[2]
def __str__(self):
return "%s" % (self.message,)
This is an example of one of the most common problems with threading. You are accessing a resource from multiple threads and the resource is not considered thread-safe (if both threads are sending/receiving at the same time, it's possible for a thread to get the wrong response, or even both responses).
Ideally you should be locking access to passCommand with a mutex so it can only be used with by one thread at a time, or opening one socket per thread, or doing all of your socket operations in a single thread.

Resources