0

I use the common tcp client to receive string messages through TCP. I want after the reception of a specific message e.g. "XXX" my client to be ready to receive a bmp image. My server in C++ sends the messages but the client does not receive the image...

After some suggestions .. se below I udated the code...

Here is my code:

TCP client:

public class TCPClient {

private String serverMessage;
public static final String SERVERIP = "192.168.1.88"; //your computer IP
public static final int SERVERPORT = 80;
private OnMessageReceived mMessageListener = null;
private boolean mRun = false;
private PrintWriter out;
private BufferedReader input;
private DataInputStream dis;
/**
 *  Constructor of the class. OnMessagedReceived listens for the messages received from server
 */
public TCPClient(OnMessageReceived listener) {
    mMessageListener = listener;
}

/**
 * Sends the message entered by client to the serveraddress
 * @param message text entered by client
 */
public void sendMessage(String message){
    if (out != null && !out.checkError()) {
        out.println(message);
        out.flush();
    }
}

public void stopClient(){

    mRun = false;
    if (out != null) {
        out.flush();
        out.close();
    }

    mMessageListener = null;
    input = null;
    input = null;
    input = null;
    serverMessage = null;
}

public void run() {

    mRun = true;
    try {
        //here you must put your computer's IP address.
        InetAddress serverAddr = InetAddress.getByName(SERVERIP);

        Log.e("TCP Client", "C: Connecting...");

        //create a socket to make the connection with the server
        Socket socket = new Socket(serverAddr, SERVERPORT);

        try {

            //send the message to the server
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

            Log.e("TCP Client", "C: Sent.");

            Log.e("TCP Client", "C: Done.");

            //receive the message which the server sends back

            dis = new DataInputStream(socket.getInputStream());
            // The buffer reader cannot can't wrap an InputStream directly. It wraps another Reader.
            // So inputstreamreader is used.
            input = new BufferedReader(new InputStreamReader(dis, "UTF-8"));

            Log.d("MyApp","We are here");
            //this.input = new DataInputStream(in);

            //in this while the client listens for the messages sent by the server
            while (mRun) {
                Log.d("MyApp", "We are here 2");
                serverMessage = input.readLine();

                if (serverMessage != null && mMessageListener != null) {
                    //call the method messageReceived from MyActivity class
                    mMessageListener.messageReceived(serverMessage);

                    Log.d("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");
                }

                if ("XXX".equals(serverMessage)) {
                    Log.d("MyApp", "We are here 3");
                    serverMessage = null;
                    while (mRun) {
                        WriteSDCard writeSDCard = new WriteSDCard();

                        writeSDCard.writeToSDFile(serverMessage);


                        }
                    }
                }
              } finally {
                socket.close();
        }
            Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");

        } catch (Exception e) {

            Log.e("TCP", "S: Error", e);

        } finally {
            //the socket must be closed. It is not possible to reconnect to this socket
            // after it is closed, which means a new socket instance has to be created.

}

}

//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
    public void messageReceived(String message);
}
}
public class WriteSDCard extends Activity {

private static final String TAG = "MEDIA";
private TextView tv;



/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
//(not needed)        setContentView(R.layout.main);
//(not needed)           tv = (TextView) findViewById(R.id.TextView01);
    checkExternalMedia();
    String message =null;
  }


 /** Method to check whether external media available and writable. This is adapted from
 http://developer.android.com/guide/topics/data/data-storage.html#filesExternal */

private void checkExternalMedia(){
    boolean mExternalStorageAvailable = false;
    boolean mExternalStorageWriteable = false;
    String state = Environment.getExternalStorageState();

    if (Environment.MEDIA_MOUNTED.equals(state)) {
        // Can read and write the media
        mExternalStorageAvailable = mExternalStorageWriteable = true;
    } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        // Can only read the media
        mExternalStorageAvailable = true;
        mExternalStorageWriteable = false;
    } else {
        // Can't read or write
        mExternalStorageAvailable = mExternalStorageWriteable = false;
    }
    tv.append("\n\nExternal Media: readable="
            +mExternalStorageAvailable+" writable="+mExternalStorageWriteable);
}

  /** Method to write ascii text characters to file on SD card. Note that you must add a
   WRITE_EXTERNAL_STORAGE permission to the manifest file or this method will throw
 a FileNotFound Exception because you won't have write permission. */

   void writeToSDFile(String inputMsg){

    // Find the root of the external storage.
    // See http://developer.android.com/guide/topics/data/data-  storage.html#filesExternal

    File root = android.os.Environment.getExternalStorageDirectory();
    tv.append("\nExternal file system root: "+root);

    // See http://stackoverflow.com/questions/3551821/android-write-to-sd-card-folder

    File dir = new File (root.getAbsolutePath() + "/download");
    dir.mkdirs();
    Log.d("WriteSDCard", "Start writing");
    File file = new File(dir, "myData.txt");

    try {
        FileOutputStream f = new FileOutputStream(file);
        PrintWriter pw = new PrintWriter(f);
        pw.println(inputMsg);
        pw.flush();
        pw.close();
        f.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        Log.i(TAG, "******* File not found. Did you" +
                " add a WRITE_EXTERNAL_STORAGE permission to the   manifest?");
    } catch (IOException e) {
        e.printStackTrace();
    }
    tv.append("\n\nFile written to "+file);
}

/** Method to read in a text file placed in the res/raw directory of the application. The
 method reads in all lines of the file sequentially. */

}

And the server side:

Code:

void sendBMP( int cs, int xs, int ys)
{
int imgdataoffset = 14 + 40;     // file header size + bitmap header size
int rowsz = ((xs) + 3) & -4; // size of one padded row of pixels
int imgdatasize = (((xs*3) + 3) & -4) * ys;    // size of image data
int filesize = imgdataoffset + imgdatasize;
int i, y;



HTLM_bmp_H HTLM_bmp_h;
HTLM_bmp_h.bmfh.bfSize = filesize;
HTLM_bmp_h.bmfh.bfReserved1 = 0;
HTLM_bmp_h.bmfh.bfReserved2 = 0;
HTLM_bmp_h.bmfh.bfOffBits = imgdataoffset;

HTLM_bmp_h.bmih.biSize = 40;
HTLM_bmp_h.bmih.biWidth = xs;
HTLM_bmp_h.bmih.biHeight = ys;
HTLM_bmp_h.bmih.biPlanes = 1;
HTLM_bmp_h.bmih.biBitCount = 24;
HTLM_bmp_h.bmih.biCompression = 0;
HTLM_bmp_h.bmih.biSizeImage = imgdatasize;
HTLM_bmp_h.bmih.biXPelsPerMeter = 1000;
HTLM_bmp_h.bmih.biYPelsPerMeter = 1000;
HTLM_bmp_h.bmih.biClrUsed = 1 << 24;
HTLM_bmp_h.bmih.biClrImportant = 0;

printf("Start Sending BMP.\n"); 

send(cs,(unsigned char *)"BM",2,0);

send(cs,(unsigned char *)&HTLM_bmp_h,sizeof(HTLM_bmp_h),0);

printf("Sending...\n"); 

Buff_ptr = 0;

send(cs, (unsigned char *)Rbuffer, BUFF_SIZE,0 );
send(cs, (unsigned char *)Gbuffer, BUFF_SIZE,0 );
send(cs, (unsigned char *)Bbuffer, BUFF_SIZE,0 );
send(cs, (unsigned char *)"\n",1,0);        
send(cs, (unsigned char *)"END\n",4,0); 
printf("Done\n\n");
}

typedef struct {
//       char    bfType1;
//       char    bfType2;
int     bfSize;
short   bfReserved1;
short   bfReserved2;
int     bfOffBits;
} BMFH;


typedef struct {
unsigned int    biSize;
int    biWidth;
int    biHeight;
short    biPlanes;
short    biBitCount;
unsigned int    biCompression;
unsigned int    biSizeImage;
int    biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int    biClrUsed;
unsigned int    biClrImportant;
} BMIH;

typedef struct {
BMFH bmfh;
BMIH bmih;
} HTLM_bmp_H;

main()
{
TSK_Handle tsk_cam;
tsk_cam=TSK_create( (Fxn)TSK_webview, NULL);
TSK_setpri(tsk_cam, 8);
}

char buffer[2048];

Void TSK_webview()
{

int s,cs;
struct sockaddr_in    addr;    /* generic socket name */
struct sockaddr    client_addr;
int sock_len = sizeof(struct sockaddr);
int frame = 0;
LgUns i=0;
int len;
int x = DSKeye_SXGA_WIDTH, y = DSKeye_SXGA_HEIGHT;

DSKeye_params CAM_params = {
....
};


lwIP_NetStart();



/**************************************************************
    *     Main loop.
***************************************************************/

s = socket( AF_INET, SOCK_STREAM, 0 );

addr.sin_port = htons(80);
addr.sin_addr.s_addr = 0;
memset(&(addr.sin_zero), 0, sizeof(addr.sin_zero));
printf("start\n");
if( bind(s, (struct sockaddr*)&addr, sizeof(struct sockaddr)))
{
    printf("error binding to port\n");
    return ;
}
printf("xx1\n");
if(DSKeye_open(&CAM_params)) {
    printf("xx2\n");      
    SYS_abort("DSKcam_CAMopen");
printf("xx3\n");  fflush(stdout);}

printf("xx4\n");

while(1==1) {
    printf("Waiting for client to be connected ... \n");
    listen(s, 10);
    cs  = accept(s, &client_addr, &sock_len);
    printf("Client connected.\n");
    send(cs,(unsigned char *)"Server connected\n",17,0);
    recv(cs, (unsigned char*)buffer, 17, 0);


    switch (*(buffer)){
        case 'A' :
        ...
        case 'B' :
        ...
    }
    REG32(0xA0000080)=REG32(0xA0000080) - 0x800000; ///Disable stepper controller vhdl Quartus Block

    for(frame = 0; frame < 4; frame++){ // Allow AEC etc to settle

       SrcFrame=DSKeye_getFrame();
    }

    printf("Demosaicing of %d x %d image is ongoing \n", x, y);     
    demosaic(SrcFrame, x, y);       
    break;

}


    printf("Demosaicing completed ...\n");
    send(cs,(unsigned char *)"Demosaicing completed\n",22,0);   
    send(cs,(unsigned char *)"XXX\n",4,0);      
    sendBMP(cs, x, y);
    fflush(stdout);         
    lwip_close(cs); 

}

the send : lwip_send

int lwip_send(int s, void *data, int size, unsigned int flags)
{
  struct lwip_socket *sock;
  struct netbuf *buf;
  err_t err;

  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, size, flags));

  sock = get_socket(s);
  if (!sock) {
    set_errno(EBADF);
    return -1;
  }

  switch (netconn_type(sock->conn)) {
  case NETCONN_RAW:
  case NETCONN_UDP:
  case NETCONN_UDPLITE:
  case NETCONN_UDPNOCHKSUM:
    /* create a buffer */
  buf = netbuf_new();

  if (!buf) {
     LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ENOBUFS\n", s));
      sock_set_errno(sock, ENOBUFS);
      return -1;
  }

  /* make the buffer point to the data that should
   be sent */
  netbuf_ref(buf, data, size);

  /* send the data */
  err = netconn_send(sock->conn, buf);

 /* deallocated the buffer */
 netbuf_delete(buf);
 break;
case NETCONN_TCP:
   err = netconn_write(sock->conn, data, size, NETCONN_COPY);
 break;
default:
  err = ERR_ARG;
  break;
 }
 if (err != ERR_OK) {
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d\n", s, err));
  sock_set_errno(sock, err_to_errno(err));
  return -1;
 }

 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ok size=%d\n", s, size));
 sock_set_errno(sock, 0);
 return size;
  }
G.V.
  • 709
  • 2
  • 11
  • 17

2 Answers2

1

You can't mix a buffered reader and a data input stream on the same socket. The buffered reader will read-ahead and steal data you expect to read via the data input stream. You will have to use the data input stream for everything. And correspondingly at the sender.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • That's exactly what i see !!! After the change in the if check as @Am_I_Helpful suggested, i see all the messages that are received (tcp messages with image parts) as exceptions leading to errors.... – G.V. Sep 03 '16 at 18:35
  • So, I think using something like: input = new BufferedReader(new InputStreamReader(dis, "UTF-8")); I will have one input that can handle messages and other data. – G.V. Sep 11 '16 at 08:43
  • Maybe. Doing it the way I said will definitely work. – user207421 Sep 11 '16 at 16:54
  • Yes, I agree, I kept one input stream and I modified it, in order to identify string messages. But when the server sends the XXX message then sends a stream of data, these data are not recieved from my app ... using wireshark or trying to store them in a file I see that only one message is received after the XXX message, the message with the header of bitmap the three bufferes are not received... – G.V. Sep 11 '16 at 17:04
0

You're doing incorrect comparison for string equality.

In Java, string comparison for equality is done using String.equals(Object anObject)

You're using if (serverMessage == "XXX") {....

You should use if ("XXX".equals(serverMessage)) {....

Am_I_Helpful
  • 18,735
  • 7
  • 49
  • 73
  • 1
    @user6657161 - Why? User asked about why his/her line was not getting printed! I gave the answer. That is it. It stands perfectly as an answer. – Am_I_Helpful Sep 03 '16 at 17:53
  • It is a part of the question not the main question, but anyway thank you a lot ! – G.V. Sep 03 '16 at 18:10
  • 1
    @GV - You asked that `we are here 3` is not getting read, I answered it. That's it. Your question doesn't have any other question clarifying what is other error, and exceptions faced if any! Please edit and clarify the details, and add exceptions faced, if any! – Am_I_Helpful Sep 03 '16 at 18:18