Re: data gets corrupted (c sockets)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



The code would be this one: (note that I have some functions from the
code from that website I mentioned before)

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <netinet/tcp.h>

#define ROOTPATH "/root/htmldocs" //just for testing, I'll change later

char *get_mime_type(char *name)
{
  char *ext = strrchr(name, '.');
  if (!ext) return NULL;
  if (strcmp(ext, ".html") == 0 || strcmp(ext, ".htm") == 0) return "text/html";
  if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".jpeg") == 0) return
"image/jpeg";
  if (strcmp(ext, ".gif") == 0) return "image/gif";
  if (strcmp(ext, ".png") == 0) return "image/png";
  if (strcmp(ext, ".css") == 0) return "text/css";
  if (strcmp(ext, ".au") == 0) return "audio/basic";
  if (strcmp(ext, ".wav") == 0) return "audio/wav";
  if (strcmp(ext, ".avi") == 0) return "video/x-msvideo";
  if (strcmp(ext, ".mpeg") == 0 || strcmp(ext, ".mpg") == 0) return
"video/mpeg";
  if (strcmp(ext, ".mp3") == 0) return "audio/mpeg";
  if (strcmp(ext, ".pdf") == 0) return "application/pdf";
  return NULL;
}

void error(char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
     int rbytes, sbytes;
     int charstobewritten;
     char buffsprint[512];
     int length;
     int file;
     char fullpath[500];
     char buf[4096];
     char * method;
     char * path;
     char * protocol;
     int sockfd, newsockfd, portno, clilen;
     char buffer[256];
     char buffer2[256];
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0)
        error("ERROR opening socket");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
              error("ERROR on binding");
     listen(sockfd,5);
     clilen = sizeof(cli_addr);
     while (1)
     {
     newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
     if (newsockfd < 0)
          error("ERROR on accept");

     bzero(buffer,256);
     n = read(newsockfd,buffer,255);
     strcpy(buffer2,buffer);
     method = strtok(buffer2, " ");
     path = strtok(NULL, " ");
     protocol = strtok (NULL, "\r");
     sprintf(fullpath, "%s%s", ROOTPATH, path);
     file = open(fullpath,O_RDONLY);

     if (file == 0)
       error ("error opening file");
     else
       {
         length = lseek(file, 0, SEEK_END);
         lseek(file, 0, SEEK_SET);
       }
     printf("Here is the path: %s\n",fullpath);

     if (n < 0) error("ERROR reading from socket");
     printf("Here is the message: %s\n",buffer);

     charstobewritten = sprintf(buffsprint, "HTTP/1.0 200
OK\r\nContent-Type: %s\r\n",get_mime_type(path));

     n = write(newsockfd, buffsprint, charstobewritten);
     printf("%s", buffsprint);
     if (n < 0) error("ERROR writing to socket");
     charstobewritten = sprintf(buffsprint, "Content-Length:
%d\r\n\r\n",length);
     n = write(newsockfd, buffsprint, charstobewritten);

     if (n < 0) error("ERROR writing to socket");
     printf("%s", buffsprint);
     while(rbytes = read(file,buf,sizeof(buf))){

       sbytes = write(newsockfd,buf,rbytes);
       if (sbytes != rbytes) printf("%d\n", sbytes); //just for
debugging purposes
    }
    close(file);
    close(newsockfd);
     }
     return 0;
}

As I mentioned before, I've changed to open/read but had no success
and I'm using these functions now for that matters.
Note that I'm using a printf to see whether the number of bytes read
from the file is the same written to the file (as nothing
shows up on the screen, it means that the same number of bytes is being sent).

Anyway, take a look at the code and you'll see.


On Mon, Jun 14, 2010 at 4:58 PM, David F <linux-net@xxxxxxxxxxxxxxxx> wrote:
>
> Al Lanot wrote:
>>
>> Yes, I've checked this before (and now again) and even tried to change
>> to open/read functions
>> to handle the file, but that's not the problem.
>>
>> Remember that I said that wget can download the files just fine though.
>>
>> On Mon, Jun 14, 2010 at 9:02 AM, Roel van Meer <rolek@xxxxxxxxxx> wrote:
>>
>>>
>>> Al Lanot writes
>>>>
>>>> My code is basically a modification of the one provided on this link (
>>>> http://www.jbox.dk/sanos/webserver.htm )
>>>> which has the same problem as well.
>>>>
>>>> The code to send the data is basically the following (it's my
>>>> modification but the original has the same problem) :
>>>>
>>>> while(ftell(file) < length){
>>>>   rbytes = fread(buf,1,sizeof(buf),file);
>>>>   sbytes = write(newsockfd,buf,rbytes);
>>>> }
>>>> fclose(file);
>>>> close(newsockfd);
>>>>
>
> There are some problems in this code, and it is also incomplete.
>
> Mistakes: you forgot to check for error return-codes from fread() and write().
> Missing: you don't give the declaration of "buf".  Or what is in "length".
>
> I also echo Roel's comment regarding fread() -- if possible, I recommend using read() and write() -- amongst other advantages, it will be more efficient.  You should also wrap your write() call into a loop in case it only wrote a partial buffer.  This is again a problem of not checking the return-codes.
>
> I furthermore recommend _not_ using ftell() to end your loop -- just loop until you reach EOF as indicated by a partially-filled (or 0-length) read (regardless of using fread() or read()).  If you really want to stop the loop when you've reached the length that you expect, regardless of EOF status, keep your own counter of how many bytes you've sent.
>
> The issue with wget() working could indicate many things, but not likely that the problem is on the other side -- perhaps it sends some different headers that don't trigger the bug.
>
> Anyhow, you really should post the entire code.  It's hard to say what the problem is when one only has a fragment of the code to look at.
>
> -- David Favro
>
--
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Photo]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]     [Video 4 Linux]