Solved

Linux Sockets - Client / Server

Posted on 2004-04-17
20
458 Views
Last Modified: 2010-04-22
I'm trying to write a client/server program under linux. The protocol is similar to FTP (using TEXT commands and answers).

My problem the following:
I'm sending from the client:
1st write:  FILE file_name_1
2nd write: FILE file_name_2

but on the server's side they end up in a single packet, containing FILE file_name_1FILE file_name_2!

I've tried setting the TCP_NODELAY option on the socket, as well as usleep()ing between writes, but they don't work!  
Any ideas?
0
Comment
Question by:Dragon_Krome
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
  • 2
  • +3
20 Comments
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10848712
Did you fflush your descriptor after each write?
Have a look to http://www.informit.com/articles/article.asp?p=22086
( "Connecting to the server" )
0
 
LVL 5

Author Comment

by:Dragon_Krome
ID: 10849573
I see in that article that they convert the standard socket descriptor into a FILE* by using fdopen.
From what I know, read/write are unbuffered, as opposed to fread/fwrite (where fflush should be used).
Or am I mistaking? Perhaps if I'd use recv/send instead of read/write ?
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10849596
The "symptoms" of your problem sound like a buffering problem.
Could you post the relevant part of your code?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 5

Author Comment

by:Dragon_Krome
ID: 10849631
This would be the relevant part.

for (parse_a_file_list...)
      {
                  snprintf(buf,sizeof(buf)-1,"FILE %s/%lu/%s",fis_scan->nume,
                                                                                    fis_scan->size,
                                                                                    fis_scan->desc);
                  write(serv_socket,buf,strlen(buf));
                  //usleep(100000);    // <---- sometimes this solves the problem
      }

I want each written() message to be read() individually....but they're in there togeter (FILE 1/343/asdsadFILE 2/3984/asdsadsa.... etc. ).

I've set TCP_NODELAY, IPTOS_LOWDELAY and even tried to set SO_SNDBUF to 0... none work. The usleep() method is working with a high interval, but it's not the way I want to do this...
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10849678
On server side, you "setsockopt" with TCP_NODELAY after the accept.
On client side did you do it as well after the connect?
0
 
LVL 5

Author Comment

by:Dragon_Krome
ID: 10849697
I was setting TCP_NODELAY just after socket(). I've tried after accept/connect too, still the same... :((
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10849738
From Google groups:
> If I connect to another host, I create a socket. If I write
> n bytes to this socket one question arises:

> * Will the operating system send this block of data
>   imedeately to the other host or will it wait for
>   another m bytes until an internal buffer is filled ?

> If so, how can I change the size of this buffer ?

> Thanks in advance,

A write() on a socket might be buffered for a (very short) time
to get data from the next write() into the same transport-paket.
If no write() is called for this short time (normally something
around 100ms) a paket (which is not completely filled) will be
sent.
Generally the data of your write() will not be buffered until
enough data for maximum paketsize is available.
(http://groups.google.com/groups?q=g:thl3166708581d&dq=&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=01bce453%246a5efdc0%24c48bca95%40samos_pc2)

Can you please try with fdopen and fflush, as it is fast to implement, to ensure that it is the problem.
0
 
LVL 5

Author Comment

by:Dragon_Krome
ID: 10849775
I've replaced some of the code with fprintf and fflush and the data doesen't get sent anymore :( .  I'll have to look into this more carefully.
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10849822
It appears that the delay you commented in your program is exactlly the 100ms of the comment above.
Since your packets are very small, it is likely that the above comment applies.

Your code should look like

   FILE *fp;
   if ((fp = fdopen(serv_socket, "w")) == NULL) {  perror("Could not open file stream from file descriptor");   return;  }

   for (parse_a_file_list...)
   {
               snprintf(buf,sizeof(buf)-1,"FILE %s/%lu/%s",fis_scan->nume, fis_scan->size, fis_scan->desc);
               fprintf(fp, buf);
               fflush(fp);
     }
0
 
LVL 45

Expert Comment

by:sunnycoder
ID: 10856413
IMHO you should be trying to modify your code to accept multiple commands rather than finding ways of flushing the socket ...

Combining several packets into one is a normal optimization carried out by most network stacks ... Your recepient should be capable of parsing and executing all the requests that it receives in any number of packets ...
This will need far less efforts, will not be platform dependent and will make your program robust ... while finding hacks for flushing the socket will need more efforts (as you might have realized by now) may be platform dependent and you may find yourself not being able to reproduce the effect in your school server
0
 
LVL 8

Expert Comment

by:da99rmd
ID: 10858346
I vote for sonnycoders example just use delimiters to part the 2 commands, an example would be:
1st write:  FILE file_name_1
2nd write: FILE file_name_2

the packet will then be.
"%STARTC%FILE file_name_1%ENDC%%STARTC%FILE file_name_2%ENDC%"
in this way you can split out the commands from the packet.

For more helpful reading on making applikcation layer protocols use smtp protocol as base its easy and very good.
http://www.freesoft.org/CIE/RFC/821/index.htm

/Rob
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10858842
I vote for Dragon_krome, as he is the requester  (:o

The concatenation is a good suggestion, but DK may have good reasons to get 2 packets.
At least now that he has the two solutions he can choose :)
0
 
LVL 5

Author Comment

by:Dragon_Krome
ID: 10866439
Guys...

I wanted a way to make this thing go away... :) I understand it's purpose, but I don't need it. I wanted to disable it,
because I was not aware at the time when I wrote my code, and adding a parser would be a pain in the a**. (I was close
to a deadline).

Mercantilum:  tried the fflush() part on a part of my code... the result: nothing was sent at all :(  dunno why.

I did this the ugly way, using usleeps()...
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10866469
You should have something like
   newsocket = accept (...);

this is the one to be used in fdopen - oh, by the way, please try with "r+" (not "w" as I mentioned before)

   if ((fp = fdopen(newsocket, "r+")) == NULL) {  perror("Could not open file stream from file descriptor");   return;  }

This should work.
0
 
LVL 8

Expert Comment

by:da99rmd
ID: 10866656
I se your problem with the time issue.
But it can  be buffered on the recieving side to.
Try altering SO_RCVBUF to on the recieving side.
But dont make them to small because then the socket will stop sending, dnot know why thou.

/Rob
0
 
LVL 4

Expert Comment

by:NVRAM
ID: 11044860
The FTP standard requires an EOL marker between commands for this reason.  

There are two simple solutions I see to your problem:
 1) essentially what da99rmd said - add a newline after each command (could be a null, or anything that will not occur in the command text),
 2) send a size word before each 'packet', like this (note that sockwrite() only handles null terminated strings, to pass in a length, just remove the 'strlen' line and make 'len' an argument)...  [I just typed that into the browser, it may not even compile, but you get the gist...]

       // Using hton() and ntoh() will acommodate big- and little-endian differences.  
       int sockwrite(int sock, const char buf[] ) {
           int len = strlen(buf);             // Might want to use 'hton()' to be platform independent...
           int rc1 = write( sock, &len, sizeof(len));
           if (rc1 != sizeof(len))
                return rc1;
           return write( sock, buf, strlen(buf));
       }

       int sockread( int sock, int& len, char buf[] ) {
           int rc1 = read( sock, &len, sizeof(len));               // Might want to use 'ntoh()' to be platform independent...
           if (rc1 != sizeof(len))
                return rc1;
           return read( sock, buf, len );
       }
0
 
LVL 45

Expert Comment

by:sunnycoder
ID: 11246227
Hi GhostMod,

I recommend to PAQ the question ... I leave it upto you to decide whether to refund or not.
0
 
LVL 5

Accepted Solution

by:
Netminder earned 0 total points
ID: 11281615
Closed, no points refunded.
Netminder
Site Admin
0

Featured Post

Containers and Docker for Everyone

Containers are an incredibly powerful technology that can provide you and/or your engineering team with huge productivity gains. Using containers, you can deploy, back up, replicate, and move apps and their dependencies quickly and easily.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
The purpose of this article is to demonstrate how we can upgrade Python from version 2.7.6 to Python 2.7.10 on the Linux Mint operating system. I am using an Oracle Virtual Box where I have installed Linux Mint operating system version 17.2. Once yo…
There are cases when e.g. an IT administrator wants to have full access and view into selected mailboxes on Exchange server, directly from his own email account in Outlook or Outlook Web Access. This proves useful when for example administrator want…
In this video, viewers will be given step by step instructions on adjusting mouse, pointer and cursor visibility in Microsoft Windows 10. The video seeks to educate those who are struggling with the new Windows 10 Graphical User Interface. Change Cu…

688 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question