Attempting to write a gets like function for tcp

Attempting to write a gets like function for tcp

Post by James Blackwel » Thu, 10 Jul 2003 14:44:23



Hello and greetings all!

I have been trying to get this code snippet to work for hours and I'm
just plain stuck.  This function is supposed to basically act like a
gets for tcp, returning a line of data each time its called (and
buffering remaining data until asked for) but fails miserably.

The algorithm that I came up with was along these lines:

while ( tcp buffer is empty | no \n in buffer) {
   grab data from the socket
   add new data to the buffer

Quote:}

get the data from the buffer up to the first newline
move the rest of the buffer to the front of the buffer
return the data that was just gathered;

The function, which fails miserably, compiles cleanly with -Wall. For
some reason gdb is not able to trace this program properly, as many
times the de* reports that variables are out of scope even when I
know that they are (verified through yet more printfs).

Is there something I'm doing obviously wrong here?

struct connection {
          int conn_no;
          int bufflen;
          char *buffer;
          char *dataend;

Quote:};

#define BUFFLEN 16384
char *tc_getline(struct connection *s) {
          char *retval;
          char *enter;
          int i;
          int bufferleft;
          int len;

          while ( s->buffer == s->dataend || !(enter=strchr(s->buffer,'\n') {

                    len = s->dataend - s->buffer;
                    bufferleft = s->bufflen - len;

                    i = recv(
                                          s->conn_no,
                                          s->dataend,
                                          bufferleft,
                                          0);

                    s->dataend[i] = '\0';
                    (s->dataend) += i;
          }
          len = enter - s->buffer+1;
          retval = strndup(s->buffer, len);

          len = s->dataend-enter;
          memmove(s->buffer, enter, s->dataend-enter);

          s->dataend -= len;

          return retval;

Quote:}

Thank you very much in advance,
James
 
 
 

Attempting to write a gets like function for tcp

Post by David Schwart » Thu, 10 Jul 2003 16:36:35



Quote:> Is there something I'm doing obviously wrong here?

    I'll stick to the most obvious stuff:

Quote:> struct connection {
>   int conn_no;
>   int bufflen;
>   char *buffer;
>   char *dataend;
> };

> #define BUFFLEN 16384
> char *tc_getline(struct connection *s) {
>   char *retval;
>   char *enter;
>   int i;
>   int bufferleft;
>   int len;

>   while ( s->buffer == s->dataend || !(enter=strchr(s->buffer,'\n') {

>     len = s->dataend - s->buffer;
>     bufferleft = s->bufflen - len;

>     i = recv(
>   s->conn_no,
>   s->dataend,
>   bufferleft,
>   0);

>     s->dataend[i] = '\0';

    Ack! What if 'i' is '-1' or zero?

Quote:>     (s->dataend) += i;
>   }
>   len = enter - s->buffer+1;

    If s->buffer==s->dataend, 'enter' may not contain anything meaningful!

Quote:>   retval = strndup(s->buffer, len);

>   len = s->dataend-enter;
>   memmove(s->buffer, enter, s->dataend-enter);

    Umm, 'enter' points to the '\n', so your buffer now starts with a '\n'!
That's certainly not what you want.

Quote:>   s->dataend -= len;

>   return retval;
> }

    That's the most serious stuff I could find.

    DS

 
 
 

Attempting to write a gets like function for tcp

Post by Derk Gwe » Thu, 10 Jul 2003 19:39:02


#
# Hello and greetings all!
#
# I have been trying to get this code snippet to work for hours and I'm
# just plain stuck.  This function is supposed to basically act like a
# gets for tcp, returning a line of data each time its called (and
# buffering remaining data until asked for) but fails miserably.
#
# The algorithm that I came up with was along these lines:
#
# while ( tcp buffer is empty | no \n in buffer) {
#    grab data from the socket
#    add new data to the buffer
# }

In my naivet?, I would be tempted to do that as
        FILE *socket = fdopen(socketnumber,"r+");
        ...
                fgets(line,sizeof(line),socket);
        ...

--
Derk Gwen http://derkgwen.250free.com/html/index.html
We found a loophole; they can't keep us out anymore.

 
 
 

Attempting to write a gets like function for tcp

Post by James Blackwel » Thu, 10 Jul 2003 23:37:36





>> Is there something I'm doing obviously wrong here?

>     I'll stick to the most obvious stuff:

>> struct connection {
>>   int conn_no;
>>   int bufflen;
>>   char *buffer;
>>   char *dataend;
>> };

>> #define BUFFLEN 16384
>> char *tc_getline(struct connection *s) {
>>   char *retval;
>>   char *enter;
>>   int i;
>>   int bufferleft;
>>   int len;

>>   while ( s->buffer == s->dataend || !(enter=strchr(s->buffer,'\n') {

>>     len = s->dataend - s->buffer;
>>     bufferleft = s->bufflen - len;

>>     i = recv(
>>   s->conn_no,
>>   s->dataend,
>>   bufferleft,
>>   0);

>>     s->dataend[i] = '\0';

>     Ack! What if 'i' is '-1' or zero?

Yes. The code, as simple as possible to get the question across, doesn't
check i for an error, which could cause really * problems if recv
bombed out.

I'm not sure I see how 0 would be a problem though. During proper
operation s->dataend should be somewhere between s->buffer and
s->buffer+s->bufflen, and would just end up writing a '\0' on another
'\0'.

Quote:

>>     (s->dataend) += i;
>>   }
>>   len = enter - s->buffer+1;

>     If s->buffer==s->dataend, 'enter' may not contain anything meaningful!

>>   retval = strndup(s->buffer, len);

>>   len = s->dataend-enter;
>>   memmove(s->buffer, enter, s->dataend-enter);

>     Umm, 'enter' points to the '\n', so your buffer now starts with a '\n'!
> That's certainly not what you want.

Certainly not! I should have enter+1 here and probably check the other
parts of the code for oneoffs. Or, should have if someone hadn't
introduced me to fdopen.

Quote:>     That's the most serious stuff I could find.

A wonderful Aussie (Dr Chris McDonald) sent me a private email
mentioning that I didn't need to write this as all; there is an
"impedance matching" fdopen which can be used to turn a socket into a
filehandle -- in simpler words, by using fdopen I'm able to use fgets!

I don't think many (any?) of the * online tutorials about using
sockets ever mention such a useful tool as fdopen. That's a real shame
because just about anyone diving into socket operations is probably
already well familiar with file operations.

Thank you very much for the advice
James

--
James Blackwell              http://www.veryComputer.com/
Owner, Inframix              570-407-0488  
Your Computer Gurus on Call

 
 
 

Attempting to write a gets like function for tcp

Post by James Blackwel » Thu, 10 Jul 2003 23:44:46




> #
> # Hello and greetings all!
> #
> # I have been trying to get this code snippet to work for hours and I'm
> # just plain stuck.  This function is supposed to basically act like a
> # gets for tcp, returning a line of data each time its called (and
> # buffering remaining data until asked for) but fails miserably.
> #
> # The algorithm that I came up with was along these lines:
> #
> # while ( tcp buffer is empty | no \n in buffer) {
> #    grab data from the socket
> #    add new data to the buffer
> # }

> In my naivet?, I would be tempted to do that as
>    FILE *socket = fdopen(socketnumber,"r+");
>    ...
>            fgets(line,sizeof(line),socket);
>    ...

Grin. I'm the naive one, not you. Shortly before you probably wrote
this a swell aussie gentleman by the name of Chris McDonald pointed
out fdopen to me. fdopen/fgets was exactly what I was looking for.

fdopen was exactly the trick for me. Now I can stop trying to implement
a tcp version of fgets as one already exists!

One thing that surprises me, though. I don't think many of the socket
examples in the wild never actually get around to mentioning that fdopen
exists.

I do appreciate the advice though. As Chris said to me in private email,
"Network coding is now so simple it's almost boring."

Again, thank you
James Blackwell

 
 
 

Attempting to write a gets like function for tcp

Post by Derk Gwe » Fri, 11 Jul 2003 00:28:38


# fdopen was exactly the trick for me. Now I can stop trying to implement
# a tcp version of fgets as one already exists!

Because of the bidirectional nature of the file, you might want to do
        setvbuf(file,0,_IOLBF,0);
                Flush buffer at the end of every output line.
        setvbuf(file,0,_IONBF,0);
                Write directly without bufferring.
so the other end of the socket gets your output to respond to
in a timely fashion.

--
Derk Gwen http://derkgwen.250free.com/html/index.html
One of the drawbacks of being a martyr is that you have to die.

 
 
 

1. Porting a DOS function which gets the Systemtime (written in C) to Linux

Hi!

Probably this problem is easy to solve. Unfortunetately I couldn't
solve it.

Background:
I need to get the Systemtime actually part of it into three variables
with the month, year and day value in order to save them into the
header of a database file so I know when the file was "last accessed".
For all that entire database I found in the public library a few
examples. These were though written for Borland and M$ Compilers which
run under DOS. I though only have my gnu Linux compiler and intent to
write that program for Linux.
So the headerfile "dos.h" does not exsit for me and also not the
functions used from that headerfile.

The actual Problem:
This is just part of the example of one of the books, I need to get
the same result but with a function of the C-library of Linux, I just
type now the entire example which runs for M$ and Borland

What I need  is a struct like the date struct or the dosdate_t struct
in a headerfile and also a function which sets the actual date then to
my created object of one of these structs like it works in the
example.
Please don't just tell me to look in the man pages or "try ctime". I
have looked up some stuff in the manpages and also in to "time.h".
What I tried did not work, brought me coredumps or is not what I need
(like getting the time since 1970 in miliseconds or so). Please try to
help me with a short example.  Thanks in advance,

Moh.

PS: Please answer me also via email, as I might not found this again.
Here is the Example:

......
int Now[3];

#ifdef TURBO_C_1_0
        struct date ToDay;
        getdate(&ToDay);
        Now[0]=ToDay.da_year-1900;
        Now[1]=ToDay.da_mon;
        Now[2]=ToDay.da_day;
#endif
#ifdef MS_C_5_1
        struct dosdate_t ToDay;
        _dos_getdate(&ToDay);
        Now[0]=ToDay.year-1900;
        Now[1]=ToDay.mon;
        Now[2]=ToDay.day;
#endif
......

2. How Secure is Linux ...?

3. Newbie: Likes to learn to write GUI programs in X11

4. Process dies

5. Question on writing c program implement cp function using UNIX system calls - read, write, etc.

6. How to print to the printer connected with the terminal?

7. How to force write function to write to device immediatly

8. sharing external SCSI drives without Sun Cluster SW

9. C function "write" cannot write more than 2 Gb

10. Problem on tcp socket:two consecutive writes takes much much longer time than single write, why?

11. pbg3/333 problems getting tcp/ip up and tcp-ing

12. vnode_pager_output: attempt to write meta-data!!!

13. attempt to write meta-data ??