Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt-interest Archive, February 2007
reading and writing with QTcpSocket


Message 1 in thread

Hello,

I am trying to write a simple telnet-like test program using QTcpSocket. I am 
testing it by connecting to a listening netcat session (cmdline: netcat -l -p 
1234). I can only get QTcpSocket.bytesAvailable() to return a positive 
integer only directly after i have called QTcpSocket.write() even if data has 
been sent to the program. The communication between the client and servers 
works as expected if i use telnet, but when i use the qt-program it doesn't 
work as expected. For details i have described the flow of events and the 
flow of the code below. I also have attached the code. To compile the source 
i embedded a shell script in the source; so hopefully you can simply execute 
the source file 'sh ./test-qtnetclient.cc' to compile it. 

How can i get QTcpSocket to mimic telnet such that i can receive data from the 
socket at any time?

Thanks, 
 --- brad


The flow of events is the following:
  # start server and client
  at time 1: server is started with netcat -l -p 1234
  at time 2: client is started with ./test-qtnetclient localhost 1234
 
  # write from client --> server
  at time 3: client enters 'hello from client'
  at time 4: server receives 'hello from client' 

  # write from server --> client (PROBLEM)
  at time 5: server enters 'hello from server'
  at time 6: client receives 0 bytes. 

  # write from client --> server
  at time 7: client enters 'hello from client, again'
  at time 8: client receives 'hello from server'
  at time 9: server receives 'hello from client, again'


The basic flow of the code is in the following in pseudo code (complete code 
is attached, to compile it i embedded a shell script in the source; so 
hopefully you can simple execute the source file 'sh ./test-qtnetclient.cc'):

  while forever
      // check for incoming data
      if qtcpsocket.bytesAvailable()
          qtcpsocket.read(read_buffer)
          qtcpsocket.waitForBytesRead()
          print read_buffer

      // check for user input data
      if user_input
          qtcpsocket.write(user_write_buffer)
          qtcpsocket.waitForBytesWritten()
      sleep(1)



#if 0
#if 0
exec_line2="g++ test-qtnetclient.cc -o test-qtnetclient -I. -I/usr/include/qt4/ -L. -lQtNetwork -lpthread -lstdc++"

echo $exec_line2

$exec_line2

exit 0
#endif // 0

#include <QtCore/QObject>
#include <QtNetwork/QTcpSocket>
#include <errno.h>
#include <fcntl.h>

int main(int argc, char ** argv)
{
    int     port        = 0;
    char *  hostname    = NULL;
    int     read_ret    = 0;
    size_t  read_syze   = 0;
    FILE *  input       = NULL;
    size_t  buf_in_syze = 512;
    int     flags       = 0;

    char    buf[512];
    char    buf_in[512];
    QTcpSocket qsocket;
    memset(buf,     0, 512);
    memset(buf_in,  0, 512);

    /* check command line args */ 
    if (argc != 3)
    {
        printf("usage: %s <hostname> <port>\n", argv[0]);
        exit(1);
    }
    port = atoi(argv[2]);
    hostname = argv[1];


    /* setup input (a.k.a stdin) for non-blocking and make it 
     * buffered per-line 
     */
    input = stdin;
    setlinebuf(input);
    flags = fcntl( fileno(input), F_GETFL, 0);
    fcntl( fileno(input), F_SETFL, flags | O_NONBLOCK );

    /* connect */
    printf("Connecting %s:%i ...\n", hostname, port);
    qsocket.connectToHost(hostname, port);
    if (qsocket.waitForConnected(5000) == false)
    {
        printf("Failed to connect\n");
        exit(1);
    }

    while(1)
    {
        /* Check if we're still connected */
        if (qsocket.state() == QAbstractSocket::UnconnectedState)
        {
            break;
        }

        /* XXX XXX XXX XXX
         *
         * bytesAvailable() will always return 0 unless write() has just been
         * called, then new data will get read from the socket.
         *
         * XXX XXX XXX XXX
         */
        /* Check if there is anything to read */
        if (qsocket.bytesAvailable() != 0)
        {
            read_ret =  qsocket.read(buf, 512);
            printf("recived[%i] '%s'\n", read_ret, buf);
            memset(buf, 0, 512);
        }   

        /* check is user typed anything to send */
        if ((read_syze = fread(buf_in, 1, buf_in_syze, input)) == 0)
        {
            /* nothing was typed */
            if (ferror(input))
            {
                /* EAGAIN is the error that is returned when the
                 * function would block. */
                if (errno != EAGAIN)
                {
                    perror("fread");
                }
            }
        }
        else
        {
            /* send data along */
            printf("buf_in = [%s], size = %i\n", buf_in, read_syze);
            int i = qsocket.write(buf_in, buf_in_syze);
            printf("write ret = %i\n", i);
            if (qsocket.waitForBytesWritten(1000))
            {
                printf("write bytes\n");
            }
            memset(buf_in, 0, buf_in_syze);
        }
        sleep(1);
    }

    return 0;
}

Message 2 in thread

On 2/3/07, bkn@xxxxxxxxxx <bkn@xxxxxxxxxx> wrote:
> Hello,
>
> I am trying to write a simple telnet-like test program using QTcpSocket. I am
> testing it by connecting to a listening netcat session (cmdline: netcat -l -p
> 1234). I can only get QTcpSocket.bytesAvailable() to return a positive
> integer only directly after i have called QTcpSocket.write() even if data has
> been sent to the program. The communication between the client and servers
> works as expected if i use telnet, but when i use the qt-program it doesn't
> work as expected. For details i have described the flow of events and the
> flow of the code below. I also have attached the code. To compile the source
> i embedded a shell script in the source; so hopefully you can simply execute
> the source file 'sh ./test-qtnetclient.cc' to compile it.
>
> How can i get QTcpSocket to mimic telnet such that i can receive data from the
> socket at any time?
>

bytesAvailable() doesn't read anything.  I believe you need an event
loop for it to work the way you expect.  Without an event loop you can
use waitForReadyRead to tell you when something is available to read.
Replace the following line:

if (qsocket.bytesAvailable() != 0)

with:

if (qsocket.waitForReadyRead(0))

-K

--
 [ signature omitted ] 

Message 3 in thread

> Replace the following line:
>
> if (qsocket.bytesAvailable() != 0)
>
> with:
>
> if (qsocket.waitForReadyRead(0))
>
Thank you very much! this worked like a charm. i knew it had to be something 
easy i was missing. 

thanks!


--
 [ signature omitted ]