why is C# getting a distorted image from a python server? - python

I'm trying to transfer camera stream from my raspberry pi to pc as fast as possible. Now I'm trying to transfer it using MJPEG method. So I have a python script on my raspberry as server:
import io
import socket
import struct
import time
import cv2
class SplitFrames(object):
def __init__(self, connection):
self.connection = connection
self.stream = io.BytesIO()
self.count = 0
def write(self, buf):
if buf.startswith(b'\xff\xd8'):
# Start of new frame; send the old one's length
# then the data
size = self.stream.tell()
if size > 0:
self.connection.write(struct.pack('<L', size))
self.connection.flush()
self.stream.seek(0)
self.connection.write(self.stream.read(size))
self.count += 1
self.stream.seek(0)
self.stream.write(buf)
server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 8001))
server_socket.listen(0)
# Accept a single connection and make a file-like object out of it
connection = server_socket.accept()[0].makefile('wb')
try:
output = SplitFrames(connection)
time.sleep(2)
cap = cv2.VideoCapture(0)
while True:
ret, img = cap.read()
ret, jpg = cv2.imencode('.jpg', img)
output.write(jpg.tostring())
connection.write(struct.pack('<L', 0))
finally:
connection.close()
server_socket.close()
that works well. Also I have a python script on my pc as client, that also works well and I receive a good stream:
import io
import socket
import struct
from PIL import Image
import cv2
import numpy as np
# Start a socket listening for connections on 0.0.0.0:8000 (0.0.0.0 means
# all interfaces)
client_socket = socket.socket()
client_socket.connect(("10.12.34.2", 8001))
connection = client_socket.makefile('rb')
try:
while True:
# Read the length of the image as a 32-bit unsigned int. If the
# length is zero, quit the loop
a = connection.read(struct.calcsize('<L'))
image_len = struct.unpack('<L', a)[0]
if not image_len:
break
# Construct a stream to hold the image data and read the image
# data from the connection
image_stream = io.BytesIO()
image_stream.write(connection.read(image_len))
# Rewind the stream, open it as an image with PIL and do some
# processing on it
image_stream.seek(0)
image = Image.open(image_stream)
cv_image = np.array(image)
cv2.imshow('Stream',cv_image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
finally:
connection.close()
client_socket.close()
But I needed to write client side on WPF, so I wrote it, but it doesn't work well. I receive distorted stream and after a few seconds WPF app breaks and gives me System.IO.FileFormatException. Here is the image from WPF:
What could be the reason of this? Thanks for any advice!
Here is the minimum reproducible code:
C#
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows;
using System.Windows.Media.Imaging;
namespace WPFTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private static bool connected = false;
private Socket sct;
private IPEndPoint ipPoint;
// TCP
private bool stopThread = false;
private Thread thread;
public MainWindow()
{
InitializeComponent();
}
private void ConnectButton_Click(object sender, RoutedEventArgs e)
{
if (!connected)
{
try
{
//this.ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), int.Parse("8001", CultureInfo.InvariantCulture));
this.ipPoint = new IPEndPoint(IPAddress.Parse("10.12.34.2"), int.Parse("8001", CultureInfo.InvariantCulture));
}
catch (Exception error)
{
return;
}
this.sct = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
stopThread = false;
thread = new Thread(() => { Listening(); });
thread.IsBackground = false;
thread.Start();
connected = true;
}
}
private void DisconnectButton_Click(object sender, RoutedEventArgs e)
{
if (connected)
{
StopListening();
connected = false;
}
}
private void Listening()
{
try
{
sct.Connect(ipPoint);
}
catch (Exception e)
{
StopListening();
connected = false;
return;
}
Thread.Sleep(1000);
try
{
while (!this.stopThread)
{
byte[] data = GetInputBytes(sct);
Application.Current.Dispatcher.Invoke(() =>
{
SetImage(data);
});
}
sct.Shutdown(SocketShutdown.Both);
sct.Close();
}
catch (Exception e)
{
StopListening();
}
}
public void StopListening()
{
this.stopThread = true;
try
{
thread.Abort();
sct.Shutdown(SocketShutdown.Both);
sct.Close();
}
catch (Exception e)
{
//
}
}
private void SetImage(byte[] array)
{
var image = new BitmapImage();
using (var mem = new MemoryStream(array))
{
mem.Position = 0;
image.BeginInit();
image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = null;
image.StreamSource = mem;
image.EndInit();
}
image.Freeze();
ImageCamera.Source = image;
}
public static byte[] GetInputBytes(Socket clientSocket)
{
byte[] rcvLenBytes = new byte[4];
clientSocket.Receive(rcvLenBytes);
UInt32 rcvLen = BytesToInt(rcvLenBytes);
byte[] rcvBytes;
byte[] clientData;
List<byte> rcvBytesList = new List<byte>();
int totalBytes = 0;
while (totalBytes < rcvLen)
{
if (rcvLen - totalBytes < 262144)
{
clientData = new byte[rcvLen - totalBytes];
}
else
{
clientData = new byte[262144];
}
int bytesReceived = clientSocket.Receive(clientData);
rcvBytesList.AddRange(clientData);
totalBytes += bytesReceived;
}
rcvBytes = rcvBytesList.ToArray();
return rcvBytes;
}
public static UInt32 BytesToInt(byte[] arr)
{
UInt32 wd = ((UInt32)arr[3] << 24) | ((UInt32)arr[2] << 16) | ((UInt32)arr[1] << 8) | (UInt32)arr[0];
return wd;
}
}
}
XAML
<Window x:Class="WPFTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="200px"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" ></ColumnDefinition>
<ColumnDefinition Width="220px" ></ColumnDefinition>
<ColumnDefinition Width="*" ></ColumnDefinition>
<ColumnDefinition Width="180px" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Column="2" Grid.Row="3" Height="60" Width="140" Content="Connect" x:Name="ConnectButton" FontSize="20" FontFamily="LilyUPC" FontWeight="Bold" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20, 80, 20, 0" Click="ConnectButton_Click"/>
<Button Grid.Column="0" Grid.Row="3" Height="60" Width="140" Content="Disconnect" x:Name="DisconnectButton" FontSize="20" FontFamily="LilyUPC" FontWeight="Bold" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="20, 80, 20, 0" Click="DisconnectButton_Click"/>
<Image Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Grid.ColumnSpan="3" Margin="10" RenderOptions.BitmapScalingMode="NearestNeighbor" RenderOptions.EdgeMode="Aliased" x:Name="ImageCamera"></Image>
</Grid>
</Window>

Thanks to #ThomasWeller for their answer in comments! As they said:
AddRange adds the whole buffer. How should it know how many bytes were received?
So I rewrote my receive method like this:
public static byte[] GetInputBytes(Socket clientSocket)
{
byte[] rcvLenBytes = new byte[4];
clientSocket.Receive(rcvLenBytes);
UInt32 rcvLen = BytesToInt(rcvLenBytes);
byte[] rcvBytes;
byte[] clientData;
List<byte> rcvBytesList = new List<byte>();
int totalBytes = 0;
while (totalBytes < rcvLen)
{
if (rcvLen - totalBytes < 262144)
{
clientData = new byte[rcvLen - totalBytes];
}
else
{
clientData = new byte[262144];
}
int bytesReceived = clientSocket.Receive(clientData);
rcvBytesList.AddRange(clientData.Take(bytesReceived).ToArray());
totalBytes += bytesReceived;
}
rcvBytes = rcvBytesList.ToArray();
return rcvBytes;
}
Changed line is: rcvBytesList.AddRange(clientData.Take(bytesReceived).ToArray());
It works fine now.

Related

Black image is received after being sent over socket from android client

I have a TCP connection between my android app and Desktop PC, where I want to send the ImageView via socket. My problem is that the image is apparently sent successfully as it has 9.7KiB. However when I try visualizing this image I get a black image and no apparent errors are thrown in the Android Studio IDE.
The android app that sends an image:
private ImageView mImageView;
mImageView = (ImageView) findViewById(R.id.frame_image);
private final OnClickListener mOnClickListener = new OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.button_camera:
if (!Check.isFastClick()) {
return;
}
if (mCameraHandler != null) {
if (mCameraHandler.isOpened()) {
if (checkPermissionWriteExternalStorage()) {
Drawable drawable = mImageView.getDrawable();
Bitmap bitmap = getBitmapFromDrawable(drawable);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0, baos);
byte[] array = baos.toByteArray();
SendImageClient sendImageClient = new SendImageClient();
sendImageClient.execute(array);
}
}
}
break;
};
public Bitmap getBitmapFromDrawable(Drawable drawable){
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
drawable.draw(canvas);
return bitmap;
}
public class SendImageClient extends AsyncTask<byte[], Void, Void> {
#Override
protected Void doInBackground(byte[]... voids) {
try {
Socket socket= new Socket("192.168.0.14",9999);
OutputStream out = socket.getOutputStream();
DataOutputStream dataOutputStream= new DataOutputStream(out);
dataOutputStream.write(voids[0],0,voids[0].length);
dataOutputStream.close();
out.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
activity_main.xml
<com.serenegiant.widget.UVCCameraTextureView
android:id="#+id/camera_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_toRightOf="#id/menu_layout" />
<com.serenegiant.widget.AutoFitTextureView
android:id="#+id/textureView"
android:layout_width="480px"
android:visibility="invisible"
android:layout_toRightOf="#id/menu_layout"
android:layout_height="640px" />
<ImageView
android:id="#+id/frame_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/camera_view"
android:layout_alignLeft="#id/camera_view"
android:layout_alignRight="#id/camera_view"
android:layout_alignTop="#id/camera_view" />
Server script.py
from socket import *
port = 9999
s = socket(AF_INET, SOCK_STREAM)
s.bind(('', port))
s.listen(1)
conn, addr = s.accept()
print("Connected by the ",addr)
with open('/home/pi/Desktop/frames_saved/image.jpg', 'wb') as file:
while True:
data = conn.recv(1024*8)
if not data: break
file.write(data)
conn.close()
Why am I getting a black image, and how can I get the actual image being displayed in ImageView sent to the desktop?
This code only create a empty bitmap
Bitmap bitmap = Bitmap.createBitmap(mImageView.getWidth(), mImageView.getHeight(), Bitmap.Config.ARGB_8888);
getBitmap from ImageView
ImageView mImageView = findViewById(R.id.image);
Drawable drawable = mImageView .getDrawable();
Bitmap bitmap = getBitmapFromDrawable(drawable);
public Bitmap getBitmapFromDrawable(Drawable drawable){
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
drawable.draw(canvas);
return bitmap;
}

Error while reading image received from socket

I have an android app that sends an image from gallery to a Python server via sockets using DataOutputStream to write to the socket in the client app. The image is loaded from external storage directory and buffered before being sent. The image is received by the server and written to disk memory. When I try to open the image it gives me: "Fatal Error reading the image file. Not a PNG". However the image occupies an actual image size of 430 KiB. When I print the data being received it gives me something that looks like a raw image:
b'\x97\xa7p\xc0\x04\xfbv\xf6\\\xed\x8a\xe9^\xbf\xa4p9\xae\x8eu:N\xb5\x8e\xcc\x06\xa6\xf1\tyL\xf3.^W\xb5RR\xd3)\x7fS\xf3\x8f\x1b\xc6\xf8\xa7\x9b\xf5\xb8\xc3f\xa9\xdf\xa1\xbd\xaa\xbeS\xbc\x84zt\xedT\xbfn|I\xfb\x0e\xfb\xae6\x18sS\x9b\x9e\xd8\xff\xc4>\xaf\xeb\xba\xbe>{\xe2\x87~\xe8\x87~\xe8\x87~\xe8\x87~\xe8\x87~\xe8\x87~\xe8\x87~\xe8\x87~\xe8\x87~\xe8\x87~\xe8\x87\xfe\xbf\xa4\xff\x07\xe5\x9f\xdc\xd5\xe2d\xc5\xcb\x00\x00\x00\x00IEND\xaeB`\x82'
b''
The text is longer but I cut it down..
The client code that loads the image from directory and writes to socket:
class send extends AsyncTask<Void, Void, Void> {
Socket s; //Socket Variable
#Override
protected Void doInBackground(Void... params) {
try {
s = new Socket("192.168.0.14", 9999);
String image = getLatestFilefromDir("/storage/emulated/0/DCIM");
File file = new File(image);
try (InputStream is = new BufferedInputStream(new FileInputStream(file));
DataOutputStream dos = new DataOutputStream(s.getOutputStream())) {
dos.writeLong(file.length());
int val;
while ((val = is.read()) != -1) {
dos.write(val);
}
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
private String getLatestFilefromDir(String dirPath){
File dir = new File(dirPath);
File[] files = dir.listFiles();
if (files == null || files.length == 0) {
return null;
}
File lastModifiedFile = files[0];
for (int i = 1; i < files.length; i++) {
if (lastModifiedFile.lastModified() < files[i].lastModified()) {
lastModifiedFile = files[i];
}
}
return lastModifiedFile.toString();
}
Python server:
#Imports modules
import socket
import datetime
date_string = datetime.datetime.now().strftime("%Y-%m-%d-%H:%M")
listensocket = socket.socket()
listenPort = 9999
numberOfConnections=1
thisIp = socket.gethostname()
listensocket.bind(('', listenPort))
listensocket.listen(numberOfConnections)
print("Started Listening")
(clientsocket, address) = listensocket.accept()
print("Connected")
fname = "/home/pi/Desktop/Images/"+date_string+".PNG"
f = open(fname, 'wb')
datain = 1
while datain:
datain = clientsocket.recv(100000000)
print(datain)
bytearray(f.write(datain))
f.close()
listensocket.close()
This answer may not be robust but does demonstrate a mechanism for efficiently transferring files from a Java application to a Python server. Certain paths are hard-coded for demonstration purposes. Also note that this may not be appropriate if the file being transferred is very large due to the fact that the entire file contents will be held in memory on the server side before writing to the target file. Obviously that can be accounted for with more elaborate code.
Here's the Java client:
package com.aprk;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class GetImage {
public static void main(String[] args) {
try {
Socket s = new Socket("localhost", 7070);
File image = new File("/Volumes/G-DRIVE Thunderbolt 3/Pictures/rgb_colour_wheel.png");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(image));
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
bos.write(nio(image.length()));
byte[] buff = new byte[4096];
int n;
while ((n = bis.read(buff, 0, buff.length)) > 0) {
bos.write(buff, 0, n);
}
bos.flush();
} catch (IOException ex) {
Logger.getLogger(GetImage.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static byte[] nio(long n) {
byte[] v = new byte[8];
int shift = 56;
for (int i = 0; i < 8; i++) {
v[i] = (byte)(n>>shift);
shift -= 8;
}
return v;
}
}
Here's the Python server:
import socket
from struct import unpack
HOST = '0.0.0.0'
PORT = 7070
def main():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, _ = s.accept()
with conn:
p = conn.recv(8, socket.MSG_WAITALL)
n = unpack('!Q', p)[0]
with open('/tmp/image.png', 'wb') as image:
while n > 0:
data = conn.recv(n)
image.write(data)
n -= len(data)
if __name__ == '__main__':
main()

'std::out_of_range' error in sending an image with sockets

I am using this code in Python to send an image with sockets (and OpenCV) to another computer:
#!/usr/bin/env python3
import socket
import cv2
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(("XXX.XXX.X.XXX", 9999))
serversocket.listen(5)
print ('server started and listening')
while 1:
(clientsocket, address) = serversocket.accept()
print ("connection found!")
img = cv2.imread('testImage.jpeg')
if (img.any()):
clientsocket.sendall(img)
It works pretty well, but at some point it eventually shuts down, showing this error message:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr: __pos (which is 140) > this->size() (which is 0)
Aborted
I have searched in forums but I can't find an answer to my problem. Anyone can help me?
EDIT:
My socket client, that receives the image, is written in C#, and the code is the following:
private void connectSocket()
{
receiveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint hostIpEndPoint = new IPEndPoint(IPAddress.Parse("XXX.XXX.X.XXX"), 9999);
receiveSocket.Connect(hostIpEndPoint);
}
private void btnImagem_Click(object sender, EventArgs e)
{
if (stream==0)
{
stream = 1;
}
else
{
stream = 0;
}
while (stream == 1)
{
connectSocket();
wait(300);
int dataSize;
int y, x, t = 0;
Bitmap bmp2 = new Bitmap(160, 120);
dataSize = 0;
byte[] b = new byte[receiveSocket.ReceiveBufferSize];
dataSize = receiveSocket.Receive(b);
if (dataSize > 0)
{
for (y = 0; y < 120; y++)
{
for (x = 0; x < 160; x++)
{
bmp2.SetPixel(x, y, Color.FromArgb(Convert.ToInt32(b[t + 2]), Convert.ToInt32(b[t + 1]), Convert.ToInt32(b[t])));
t = t + 3;
}
}
}
videoBox.Image = bmp2;
receiveSocket.Close();
wait(10);
}
videoBox.Image = null;
}
public void wait(int milliseconds)
{
System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
if (milliseconds == 0 || milliseconds < 0) return;
timer1.Interval = milliseconds;
timer1.Enabled = true;
timer1.Start();
timer1.Tick += (s, e) =>
{
timer1.Enabled = false;
timer1.Stop();
};
while (timer1.Enabled)
{
Application.DoEvents();
}
}

Reading image file via Socket in Python

I am trying to read an image file via a Python socket. My current attempt is the following:
while True:
data = clientsocket.recv(1024)
receivedMessage = (data.decode(encoding='UTF-8')).strip()
if ("getFile" in receivedMessage):
f = open("test2.jpg","wb")
file_size = int(receivedMessage.replace('getFile',''))
# Message: e.g. getFile28049994
read_bytes = 0
print("READING FILE")
while file_size > read_bytes:
print("RECEIVING FILE")
bytes_read = clientsocket.recv(1024)
if not bytes_read:
print("END OF FILE")
print("CHECKPOINT") # this is never printed out
read_bytes = len(bytes_read)
#writing to file
The file is sent via Android as a byte array:
Client class:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client extends AsyncTask<String, Void, Void> {
private MainActivity activity;
private Exception exception;
private byte[] data;
private String dataString;
public Client(MainActivity activity,byte[] data){
this.activity = activity;
this.data = data;
}
public Client(MainActivity activity,String dataString){
this.activity = activity;
this.dataString = dataString;
}
protected Void doInBackground(String... command) {
try{
Socket client = new Socket(".....", 50000);
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
if (data != null){
out.print(data);
}
if (dataString != null){
out.println(dataString);
}
String receivedMessage;
if ((receivedMessage = in.readLine()) != null){
if (receivedMessage.equals("connectionSuccessful")){
Intent intent = new Intent();
intent.setAction("sendServerMessage");
intent.putExtra("msg",receivedMessage);
activity.sendBroadcast(intent);
}
Log.e("Debug",receivedMessage);
}
client.close();
} catch(UnknownHostException e) {
Log.e("Exception","Unknown host");
}
catch(ConnectException e) {
Intent intent = new Intent();
intent.setAction("sendServerMessage");
intent.putExtra("msg","connectionFailed");
activity.sendBroadcast(intent);
Log.e("Exception","No I/O"+e);
}
catch (Exception e){
Log.e("Exception",""+e);
}
return null;
}
}
And the execution of the client:
new Client(activity, bytes).execute(); // bytes is a byte array (checked it)
Any idea why it is not received? Is it because I am calling two times clientsocket.recv? And how could I fix it? Thanks in advance.

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