Streaming camera from Python to C# over sockets? - python

I need to stream video from a Raspberry Pi's camera (Python server), to a C# script client (Unity, in fact).
I have successfully done this, using a Python to Python workflow, but I can't manage to make It work on C# client side.
This is my python server, where I'm sending the Stream over sockets:
Server.py:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 24000))
s.listen(1)
connection = s.accept()[0].makefile('wb')
print ('Client connected')
while True:
stream = io.BytesIO()
for foo in camera.capture_continuous(stream, 'jpeg'):
connection.write(struct.pack('<L', stream.tell()))
connection.flush()
stream.seek(0)
connection.write(stream.read())
stream.seek(0)
stream.truncate()
And this is my Python client side, which is actually working:
Client.py:
def threadLoop(self):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((self.ip, self.port))
connection = self.socket.makefile('rb')
print('Recibiendo fotos')
while not self.haltSignal():
image_len, image_width, image_height = struct.unpack('<LLL', connection.read(struct.calcsize('<LLL')))
print ("L: " + str(image_len) + " W: " + str(image_width) + " H: " + str(image_height))
if not image_len:
break
image_stream = io.BytesIO()
image_stream.write(connection.read(image_len))
image_stream.seek(0)
self.callback(image_stream.getvalue(), image_width, image_height)
self.socket.close()
self.socket = None
self.thread = None
So, the question is... having this Server.py, how can I make a C# client that receives the stream and show the pictures?
I've tried to capture the received data in C#, over the socket, store It in a Byte array and convert It to a readable image, which sometimes, when It's a (very)small sized picture, works fine. I guess there must be a better way to achieve this.
Thanks!
Edit: This is what I've been trying in C#. Thanks again!
public int Connect()
{
if (_clientSocket.Connected == false)
{
_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
mutexToSend = new Mutex();
mutexReceived = new Mutex();
ThreadStart ts = new ThreadStart(SendReceiveData);
threadSend = new Thread(ts);
threadSend.Start();
return 1;
}
else
return 0; //There is a socket already connected.
}
//----------------------------------------------------------
private void SendReceiveData()
{
try
{
_clientSocket.SendTimeout = 1000;
_clientSocket.ReceiveTimeout = 1000;
System.Net.IPAddress ipaddress = this.serverIP;
_clientSocket.Connect(new IPEndPoint(ipaddress, this.serverPort));
}
catch (SocketException ex)
{
//turn ex.Message;
}
_clientSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}
//----------------------------------------------------------
private void ReceiveCallback(IAsyncResult AR)
{
//Check how much bytes are recieved and call EndRecieve to finalize handshake
int recieved = _clientSocket.EndReceive(AR);
if (recieved <= 0)
{
GestorCamaraSala.imgReceived = _recieveBuffer; //I copy the received data to the image texture
return;
}
//Start receiving again
_clientSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}// end ReceivedCallback

Related

sending data to a Server implemented in other language

i'm having a serializabled object from class called Account. this object must be send from one device to other device using socket programing. the problem is that the Server in written in Python and the Client class written in java , some people say that it is possible to write Server class in a language different from the Client class. is there any way to do that ??
here is my code...
Client class ( Java )
public class CLIENT
{
static Socket s;
static OutputStream outputStream;
static InputStream inputStream;
static ObjectInputStream dis;
static ObjectOutputStream dos;
// Acccunt class
static class Account implements Serializable
{
String account_id = "";
int amount = 0;
}
public static void main(String[] args)
{
int Port = 50007;
try
{
Socket s = new Socket("localhost", Port);
System.out.println("Client trying to connect to port "+Port);
OutputStream outputStream = s.getOutputStream();
ObjectOutputStream dos = new ObjectOutputStream(outputStream);
InputStream inputStream = s.getInputStream();
ObjectInputStream dis = new ObjectInputStream(inputStream);
System.out.println("Ready to communicate");
while (true)
{
Account obj = new Account();
obj.account_id = "123"; obj.amount = 10000;
dos.writeObject( obj );
dos.flush();
String inn = (String) dis.readObject();
System.out.println("Server: " + inn );
}
}
catch (Exception ex) { ex.printStackTrace(); }
} // END of main
} // End of Class
Server Code ( Python )
import socket, pickle
class Account:
account_id = ""
amount = 0
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
conn, addr = s.accept()
print ('Connected by', addr)
data = conn.recv(4096)
data_variable = pickle.loads(data)
print( data_variable.account_id )
conn.send('Thank you for connecting'.encode())
conn.close()

Continuously Send Data from Android Client to Python Server Socket

I am currently trying to send ble data from the app to my PC using sockets. As of now, I am able to send data to the server, but the server only receives one data and then stops receiving. I am suspecting that there is something wrong with my client side code. Any help would be appreciated
My SocketClass code:
inner class SocketClass{
fun doInBackground(message: String): String {
try {
socket = Socket(SERVER_IP, SERVERPORT)
val outputStream = OutputStreamWriter(socket?.getOutputStream())
val printwriter = BufferedWriter(outputStream)
printwriter.write(message)
printwriter.flush()
printwriter.close()
socket?.close()
} catch (e: Exception) {
e.printStackTrace()
}catch (e: UnknownHostException){
}
return ""
}
}
and in the blereadcharacteristic I call the class in a thread like this:
private fun readDeviceCharacteristic(characteristic: BluetoothGattCharacteristic) {
var hashval:MutableMap<String, String> = mutableMapOf()
var mainThreadList :MutableList<String> = mutableListOf()
var currentTime: String = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").withZone(
ZoneId.of("Asia/Seoul")).format(Instant.now()) // Get current Timestamp
if(idlist.size != 0) {
readval = characteristic.getStringValue(0)
valdata = readval.subSequence(3, readval.length).toString()
idNo = readval.subSequence(0, 2).toString()
parseList.add(readval)
mainThreadList = parseList.toMutableList().distinctBy{it.subSequence(0, 2)} as MutableList<String>
if(mainThreadList.size == maxConnLimit) {
bleDataList = mainThreadList
bleDataList.forEach{
hashval[it.subSequence(0, 2).toString()] = it.subSequence(3, it.length).toString()
}
loghash = hashval.toSortedMap()
txtRead = bleDataList.toString()
parseList.clear()
if(isChecked) {
savehash["Time"]?.add("$sec.$millis")
bleDataList.forEach {
savehash[it.subSequence(0, 2).toString()]?.add(
it.subSequence(
3,
it.length
).toString()
)
}
}else{
time = 0
sec = 0
millis = ""
}
if(isInsert){
Thread{
SocketClass().doInBackground("$loghash\r\n\r\n")
}.start()
}
}
}
isTxtRead = true
bleDataList.clear()
}
My server socket python code:
import socket
import sys
host = '19.201.12.12'
port = 30001
address = (host, port)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(address)
server_socket.listen(5)
print("Listening for client . . .")
conn, address = server_socket.accept()
print("Connected to client at ", address)
while True:
output = conn.recv(2048);
if output.strip() == "disconnect":
conn.close()
sys.exit("Received disconnect message. Shutting down.")
elif output:
print("Message received from client:")
print(output)
I am able to get the first data sent, but do not receive anything after. Any help would be greatly appreciated thankyou!
Your server code only accepts one client connection. So, here's the timelime.
Python waits at accept.
Kotlin connects
Python moves into while True loop.
Kotlin writes, then closes the socket.
At that point, nothing further will be received by the Python code, but because you never call accept again, you can't accept another connection.
You need to have the accept in a loop. You handle that connection until it closes, then you loop to another accept.
You might consider using the socketserver module, which automates some of this.

Sending Real Time images captured using unity camera

server
private void SendImageByte()
{
image_bytes = cm.Capture();
print(image_bytes.Length);
if (connectedTcpClient == null)
{
return;
}
try
{
// Get a stream object for writing.
NetworkStream stream = connectedTcpClient.GetStream();
if (stream.CanWrite)
{
// string serverMessage = "This is a message from your server.";
// Convert string message to byte array.
byte[] serverMessageAsByteArray = Encoding.ASCII.GetBytes(image_bytes.ToString());
// Write byte array to socketConnection stream.
stream.Write(serverMessageAsByteArray, 0, serverMessageAsByteArray.Length);
Debug.Log("Server sent his message - should be received by client");
}
}
catch (SocketException socketException)
{
Debug.Log("Socket exception: " + socketException);
}
}
client
import socket
host = "127.0.0.1"
port = 1755
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
def receive_image():
data = sock.recv(999999).decode('utf-8')
print(len(data))
while True:
receive_image()
here script capture images from unity camera
public byte[] Capture()
{
if(renderTexture == null)
{
// creates off-screen render texture that can rendered into
rect = new Rect(0, 0, captureWidth, captureHeight);
renderTexture = new RenderTexture(captureWidth, captureHeight, 24);
screenShot = new Texture2D(captureWidth, captureHeight, TextureFormat.RGB24, false);
}
// _camera = GetComponent<Camera>();
_camera.targetTexture = renderTexture;
_camera.Render();
// reset active camera texture and render texture
_camera.targetTexture = null;
RenderTexture.active = null;
// read pixels will read from the currently active render texture so make our offscreen
// render texture active and then read the pixels
RenderTexture.active = renderTexture;
screenShot.ReadPixels(rect, 0, 0);
screenShot.Apply();
byte[] imageBytes = screenShot.EncodeToPNG();
//Object.Destroy(screenShot);
//File.WriteAllBytes(Application.dataPath + "/../"+ imagePath + "/img{counter}.png", bytes);
//counter = counter + 1;
return imageBytes;
}
Am trying to send real-time images on Unity3D from C# to python using socket communication to be processed and return back values to unity, but the problem even the bytes length received on the client is not the same as the server. I send about 400K bytes but I receive only 13
C# is the server and python is the client
or am doing it wrong but the main goal I want to create simulator work as udacity self-driving
Are you sure that image_bytes.ToString() returns what you expect and not maybe just something like "System.Byte[]" => 13 chars => 13 bytes.
In general why would you convert an already byte[] into a string just in order to convert it back into byte[] to send? I'm pretty sure you do not want to transmit binary image data using UTF-8 ... one option might be Base64 string, but still that would be quite inefficient.
Just send the raw bytes like e.g.
stream.Write(image_bytes, 0, image_bytes.Length);
And then receive until you receive that length.
A typical solution is to prepend the length of the message to send and on the receiver side actually wait until you received exactly that amount of bytes like e.g.
var lengthBytes = BitConverter.GetBytes(image_bytes.Length);
stream.Write(lengthBytes, 0, lengthBytes.Length);
stream.Write(image_bytes, 0, image_bytes.Length);
Now you know that on the receiver side you first have to receive exactly 4 bytes (== one int) which will tell you exactly how many bytes to receive for the actual payload.
Now I'm no python expert but after googling around a bit I think something like
def receive_image()
lengthBytes = sock.recv(4)
length = struct.unpack("!i", lengthBytes)[0]
data = sock.recv(length)
Note: After reading John Gordon's comment on the question I guess this still doesn't fully solve the waiting until according buffers are actually filled - as said no python expert - but I hope it gives you a idea where to go ;)

C WebServer and Python Client

I made a simple webserver using c. I can connect to it via a web browser and it works fine.
The goal of this webserver was to exploit it. So I wrote a simple python script that sends malicious data to the server. However, I only get an error message on the server saying: "Bad file descriptor".
C-Server Main:
int main(void) {
int sockfd, new_sockfd, yes=1;
struct sockaddr_in host_addr, client_addr;
socklen_t sin_size;
printf("Accepting web requests on port %d\n", PORT);
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
error_and_exit("in socket");
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
error_and_exit("setting socket option SO_REUSEADDR");
host_addr.sin_family = AF_INET;
host_addr.sin_port = htons(PORT);
host_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(host_addr.sin_zero), '\0', 8);
if (bind(sockfd, (struct sockaddr *)&host_addr, sizeof(struct sockaddr)) == -1)
error_and_exit("binding to socket");
if (listen(sockfd, 20) == -1)
error_and_exit("listening on socket");
while(1) { // Accept loop
sin_size = sizeof(struct sockaddr_in);
new_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);
if(new_sockfd == -1)
error_and_exit("accepting connection");
handle_connection(new_sockfd, &client_addr);
}
return 0;
}
python code:
import socket
import struct
import sys
import time
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('127.0.0.1', 8000)
sock.connect(server_address)
shellcode =(....)
values = ....
try:
sock.sendall(values)
finally:
sock.close()
Notes:
1.
the accept function (from <sys/socket.h>) in the while(1) loop returns -1, calling error_and_exit("accepting connection"). So the Server never executes handle_connection for my python client.
2.
Code for error_and_exit function:
void error_and_exit(char *message) {
char error_message[100];
strcpy(error_message, " Error ");
strncat(error_message, message, 83);
perror(error_message);
exit(-1);
}

C++ GUI freezes during communication over socket thread with Python

First of all I want to mention that I've gone through a lot of socket threading tutorials before attempting to integrate it into my own GUI, but I still consider myself fairly new to the subject.
I have a server written in python that opens a socket and starts a thread over localhost, and listens over the port for a client:
def StartThread():
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((TCP_IP, TCP_PORT))
threads = []
tcpsock.listen(5)
print "Waiting for incoming connections from client..."
(conn, (ip,port)) = tcpsock.accept()
print 'Got connection from ', (ip,port)
newthread = ClientThread(ip,port,conn, 1)
newthread.start()
return newthread
Here is the ClientThread class:
class ClientThread(Thread):
def __init__(self,ip,port,sock, status):
Thread.__init__(self)
self.ip = ip
self.port = port
self.sock = sock
self.status = 1
print " New thread started for "+ip+":"+str(port)
After I run the server code, I click a button on my C++ GUI which runs the client code StartConnection() based off the Microsoft Winsock client template.
void CPSR_CRSDlg::OnBnClickedInit2()
{
if(!checkTimerStarted())
// Set mmtimer to aquire the data
{
m_ntimerID = timeSetEvent( TIMERINTRRVAL,
1,
timerHandler,
0,
TIME_PERIODIC);
SetTimer(1,TIMERINTRRVAL_2,NULL);
m_bTimer_started = true;
}
StartConnection();
}
The connection does start successfully and the python code prints the address of the connection and the thread, but then my GUI freezes, so that I can't click any of the other buttons to actually send data over the connection.
Why does my application freeze? Am I not instantiating the thread correctly?
The StartConnection() code is off the msdn website but here is my slightly modified version if needed:
void StartConnection(){
//printf("Connection Starting... \n");
WSADATA wsaData;
ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
int argc = 2;
// Validate the parameters
if (argc != 2) {
printf("usage: %s server-name\n", "client");
return;
}
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
//iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
iResult = getaddrinfo("localhost", DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return;
}
return;
}
void StopConnection(){
closesocket(ConnectSocket);
WSACleanup();
return;
}
void SendJointValues(double *joints){
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
j = parseJSON(joints[0],joints[1],joints[2],joints[3], \
joints[4],joints[5]);
int x = send(ConnectSocket, j, strlen(j), 0);
//iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
}
Edit:
The GUI does respond again after I send data via the server, and the client then successfully sends back one iteration of data. But after this exchange the GUI freezes again until more data is sent.
Here is the send+receive portion of the server:
def receiveData(self):
while (self.status == 1):
joints = [0,0,0,0,0,0]
self.sock.sendall('send')
print "Data Sent!"
data = self.sock.recv(4096)
print "Data received: ", data
self.checkStatus(data)
print "Status is: ", self.status
if (self.status == 1):
data_loaded = json.loads(data)
joints = self.createJointArr(data_loaded['Joints'])
time.sleep(0.5)
print joints
return joints
And the SendJointValues() in the client is called in this Timer function:
void CPSR_CRSDlg::OnTimer(UINT_PTR nIDEvent)
{
CString str;
long Position;
double engPosition;
double dblPosition;
double dblSpeed;
bool ret;
// Arch
USB4_01.Controller_3.getEncoderPosition(Position);
countTodegree(Position,engPosition,ARCH);
str.Format(_T("%10.2f"),engPosition);
m_staPosArch.SetWindowText(str);
// Wrist Pitch
USB4_01.Controller_2.getEncoderPosition(Position);
countTodegree(Position,engPosition,TILT);
str.Format(_T("%10.2f"),engPosition);
m_staPosPitch.SetWindowText(str);
// Linear
USB4_02.Controller_1.getEncoderPosition(Position);
countTodegree(Position,engPosition,LINEAR);
str.Format(_T("%10.2f"),engPosition);
m_staPosLinear.SetWindowText(str);
// Turret
USB4_02.Controller_2.getEncoderPosition(Position);
countTodegree(Position,engPosition,TURRET);
str.Format(_T("%10.2f"),engPosition);
m_staPosTurret.SetWindowText(str);
// Roll
USB4_02.Controller_4.getEncoderPosition(Position);
countTodegree(Position,engPosition,ROLL);
str.Format(_T("%10.2f"),engPosition);
m_staPosRoll.SetWindowText(str);
// Drill/Tool
USB4_02.Controller_3.getEncoderPosition(Position);
countTodegree(-Position,engPosition,DRILL);
str.Format(_T("%10.2f"),engPosition);
m_staPosDrill.SetWindowText(str);
// For Penetrate joint
if(JntPenetration.isInitialized())
{
// Get Position feedback
ret = JntPenetration.getPosition(dblPosition);
if(ret) // get position feedback successfully
{
Position = (long) dblPosition;
countTodegree(Position,engPosition,PENETRATE);
str.Format(_T("%10.2f"),engPosition);
m_staPosPenetrate.SetWindowText(str);
m_dCurentPentrationPosition = engPosition;
}
// Get Speed feedback;
if(m_bDrilling_started)
{
// Penetration position close enough AND At least on cycle reached
if( (abs(engPosition - m_dDrilling_target_position) < 0.1) &&(m_Direction_Changed == true))
m_bPenetrationStopped = true;
else
m_bPenetrationStopped = false;
//JntPenetration.getSpeed(dblSpeed);
//if(dblSpeed < .05 )
// m_bPenetrationStopped = true;
//else
// m_bPenetrationStopped = false;
}
}
SendJointValues(JointArray);
// For drilling motion control
if(m_bDrilling_started)
drilingProcedure();
CDialog::OnTimer(nIDEvent);
}

Categories