Thread: File Server Help

  1. #91
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    I'm sorry but I think I've done almost all you have told me.. what's wrong? I've been correcting every mistake I had, I only have some few silly mistakes in integer and long comparison and things like that, nothing related to recv and send.

    Look, this is the server..
    Code:
    lautarox@lautarox-desktop:~/Escritorio/codigo c$ gcc -std=c99 -pedantic -Wall -Werror -Wextra fileserver.c -o fileserver
    cc1: warnings being treated as errors
    fileserver.c: En la función ‘passwdcheck’:
    fileserver.c:38: aviso: comparación entre signed y unsigned
    fileserver.c: En la función ‘recievefile’:
    fileserver.c:80: aviso: se sugieren paréntesis alrededor de la asignación usada como valor verdadero
    fileserver.c:84: aviso: comparación entre signed y unsigned
    fileserver.c: En la función ‘main’:
    fileserver.c:170: aviso: el puntero que apunta en el paso del argumento 3 de ‘accept’ difiere en signo // only this worries me, buty the connection is accepted, so.. this says that the pointer that points the third argument of accept differs from sign
    fileserver.c:120: aviso: variable ‘j’ sin usar

  2. #92
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    Sorry, double posted
    Last edited by lautarox; 09-16-2008 at 09:44 AM.

  3. #93
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I think almost all of your problems are related to mixing signed and unsigned. You SHOULD take care about using either unsigned or not unsigned depending on the criteria. Whilst warnings are "ok" to ignore, one problem with just letting the warnings be is that once in a while you get warnings that are actually REAL problems, and if you get several dozen warnings anyways, it's quite likely that there is a new one that will tell you why the code won't work.

    There is another warning about asigning in condtionals:
    If you do something like "if( x = func() )", the compiler will give you a warning. You need to do "if( (x = func() ) ) " to show that you ACTUALLY MEAN to assign something inside the conditon line, rather than compare something.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #94
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    Ohh thanks, I'll take the warnings more seriously, I didn't knew about the () inside the if, what about this error?
    Code:
    fileserver.c:170: aviso: el puntero que apunta en el paso del argumento 3 de ‘accept’ difiere en signo // only this worries me, buty the connection is accepted, so.. this says that the pointer that points the third argument of accept differs from sign
    And this
    Code:
    if(fwrite(buff, 1048576, 1, file) == -1) {
    Why does it says this?
    Code:
    fileserver.c:85: aviso: comparación entre signed y unsigned
    Last edited by lautarox; 09-16-2008 at 10:33 AM.

  5. #95
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Maybe that was a little harsh. You said you had to send everything twice, which meant that you weren't compiling with your warnings turned up, and you didn't do anything about the fd_sets not being recreated on every select call, and you didn't ask any questions about these in case you didn't understand them so it seemed like you were just brushing me off and it got on my nerves. Sorry about that.

    Basically pretty much all your compiler errors can be figured out by looking at the man pages for the various functions that are involved. For example:
    fileserver.c: In function 'passwdcheck':
    fileserver.c:38: warning: comparison between signed and unsigned
    Go to line 38:
    Code:
    for(i=0;i<strlen(buff)+1;i++) {
    Let's check to function prototype for strlen in the man page. Type man strlen at the shell prompt.
    NAME
    strlen - calculate the length of a string

    SYNOPSIS
    #include <string.h>

    size_t strlen(const char *s);
    We can see that strlen returns type size_t. Let's go back to the code. What is the result of strlen being compared to? i. What is i? It's a char, which could be either signed or unsigned. So how do we get rid of this warning? Well, you could change char i to unsigned char i or unsigned int i or size_t or whatever. size_t is unsigned, and it is the same type that strlen returns, so it would be ok.

    But all this it pointless, because the code does the same thing as strlen, and it uses strlen to do it, many many times more inefficiently than just using it once. It's completely pointless code that I recommended you get rid of before, but you didn't do that obviously, for what reason I don't know, because you didn't say anything about it. But I think it's best you just delete it.

    Let's take the next one. Line 84. it's with the fwrite function. Go to the fwrite man page. it says fwrite returns what? A size_t. size_t is unsigned, as we have just learned. Look at what it's comparing it with. a -1. What does fwrite return?
    RETURN VALUE
    fread() and fwrite() return the number of items successfully read or written (i.e., not the number of characters). If an error occurs, or the end-of-file is reached, the return value is a short item count (or zero).
    So nowhere does it return -1. That would make sense, since the return type of fwrite, size_t, cannot hold a negative value, because it is unsigned. This fwrite error was already pointed out to you by vart in post 34. You didn't fix that. Why? I don't know. You didn't mention anything, you didn't ask any questions about it, so I assumed you took the suggestion and applied the changes. But did you do that?

    Let's go to fileserver.c
    fileserver.c:170: warning: pointer targets in passing argument 3 of 'accept' differ in signedness
    Go to line 170 of fileserver.c.
    Code:
    if((newfd = accept(listener, (struct sockaddr *)&clientaddr, &addrlen)) == -1) {
    Let's go to the man page for accept and see what the type is of parameter 3. Type man 2 accept.

    NAME
    accept - accept a connection on a socket

    SYNOPSIS
    #include <sys/types.h> /* See NOTES */
    #include <sys/socket.h>

    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    ok, it's a socklen_t *.

    what do you have? an int *. So what do you do? You change the type of your addrlen variable to type socklen_t instead of type int.

    As for fork, I don't know what you were asking whether it was what I think about fork vs select vs other methods of concurrent connections, how you should change you code to use fork instead of select, what fork is, or something else. You need to be more specific with your questions.

    Hope that helps.
    Last edited by robwhit; 09-16-2008 at 06:59 PM.

  6. #96
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    Ohh that was really helpful, I'm really, really sorry of spending so much of you'r time, I'm really very thankful about your effort on making me understand everything..
    I thought you said that the error on the select was the part where it looked if there was an error or it was not active..

  7. #97
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Well, since the fd_sets are used with select, it might interfere with the way it works. I'd say that it probably would. But as to whether that's what is causing your problem I don't know, since I didn't bother to figure out what it did when it was broken, only why it wasn't doing what it was supposed to.

    I don't mind spending time on this, just that you pay attention or ask specific questions when you don't understand is all.

  8. #98
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    Well.. I've running some testing on the server and the client, and it was recieving the path and the parts, but no the "haslastpart" var, and now, don't know why, it's not recieving, even the path, I've modified the send and recv, so it has only one per send and recv, but I got to solve the problem with the select that's causing me all this trouble.
    I took the select example from a chat server, that was on a webpage, and it worked perfectly, thats why I'm really confused too, the errors like the fwrite one and the accept were taken from the website..
    What do you think it may be causing me problems inside the select?
    Last edited by lautarox; 09-16-2008 at 11:57 AM.

  9. #99
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    edit: this isn't in response to the message just above this one.

    Read these man pages:

    man select
    man select_tut
    man recv
    man send
    man fork

    There are also some networking web pages on a sticky in the networking forum.

    The reason you have to receive chunks with select instead of the whole file at the same time is because select works on the principle of asynchronous communication. That means that information comes down the wire in chunks, and the program is free to do other things in the meantime. Another type of communication is synchronous communication. This is the type you use when you use blocking sockets, or fork or threads and blocking sockets. You basically stay until the connection is closed, and your program does not do anything else if it's waiting for data to come down the pipe. This is easier to code for, and you might want to do that instead, I don't know.

    select pros:
    highly scalable to large numbers of connections

    select cons:
    uses asynchronous programming model that can be difficult to code for if you don't already have an asynchronous model in your program.

    fork pros:
    provides program independence from other parts of the program. if one part crashes, the whole program doesn't have to go down with it.
    fork can be used to have concurrent connections while still having a synchronous communication model, making programming easier.

    fork cons:
    heavyweight processes take up more resources than other alternatives. not as scalable to large numbers of connections.

    threading with blocking sockets pros:
    synchronous model with blocking sockets == programming easier
    more lightweight than forks. Since you only have threads instead of processes, it doesn't take up as much resources.

    threading cons:
    can be difficult to code shared-data and inter-thread communications
    not sure what else.

  10. #100
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    Well I think, I'll go for the hard way.. I'm thinking in a simplier function that creates a static struct (the static ones are the ones that remain after a function execution right?) with some info inside of it, total parts, parts in the moment, file name, etc and use the information to allocate the file contents.
    I'll give it a try..

  11. #101
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Quote Originally Posted by lautarox View Post
    Well.. I've running some testing on the server and the client, and it was recieving the path and the parts, but no the "haslastpart" var, and now, don't know why, it's not recieving, even the path, I've modified the send and recv, so it has only one per send and recv, but I got to solve the problem with the select that's causing me all this trouble.
    I took the select example from a chat server, that was on a webpage, and it worked perfectly, thats why I'm really confused too, the errors like the fwrite one and the accept were taken from the website..
    What do you think it may be causing me problems inside the select?
    Source code from the internet is not always the best example out there (yes, I am aware of the irony of that statement).

    ok.... fix all the errors you know about. don't worry about the symptoms, because you already know you have errors. so get rid of all the double sends and fix the fd_sets and whatever else.
    Well I think, I'll go for the hard way.. I'm thinking in a simplier function that creates a static struct with some info inside of it, total parts, parts in the moment, file name, etc and use the information to allocate the file contents.
    I'll give it a try..
    Ok. (I don't know what the hard way is, but I guess that's ok if you know)

  12. #102
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    What's the max amount of data do you recommend me to send at once?
    And can something like this be done in c?
    Code:
    for(i=0;i<max;i++) {
    i.id = 1;
    }
    Last edited by lautarox; 09-16-2008 at 12:35 PM.

  13. #103
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    I'd recommend some multiple of 2.. say 512 or so. But why do you want to know that? you're not going to send the whole file in one large send call. the send call only fills up the kernel buffer and then returns, however large that is, or however large the remaining space is. You don't know how much that is. So you'll have to get the return value of send and use it to calculate how much stuff has been sent and then continue from where it left off. Then you'll have to send it again, until it's all sent.

    If you're using blocking sockets, then you would just put the send call in a loop and recalculate the start position for each call to send.

    If you're using select in a loop, then you have to calculate the start of the next call to send and also make sure that socket is in the send fd_set for the next call to select.

  14. #104
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    Well.. I was thinking in multiple small parts to send the file, 512 bytes each part and allocate them where they belong and how you said, checking if it has sended the correct ammount of bytes.. what do you think of that?
    What about the for and the i var there?

  15. #105
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Don't store the whole file in memory. Instead, do it bit by bit like this:

    server:
    recv 512 (or less) bytes from socket into buffer
    save buffer into file
    recv 512 (or less) bytes from socket into buffer
    save buffer into file
    recv 512 (or less) bytes from socket into buffer
    save buffer into file
    recv 512 (or less) bytes from socket into buffer
    save buffer into file

    client:
    recv 512 (or less) bytes from socket into buffer
    save buffer into file
    recv 512 (or less) bytes from socket into buffer
    save buffer into file
    recv 512 (or less) bytes from socket into buffer
    save buffer into file
    recv 512 (or less) bytes from socket into buffer
    save buffer into file
    Quote Originally Posted by lautarox View Post
    And can something like this be done in c?
    Code:
    for(i=0;i<max;i++) {
    i.id = 1;
    }
    No. What are you trying to do?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need Help Fixing My C Program. Deals with File I/O
    By Matus in forum C Programming
    Replies: 7
    Last Post: 04-29-2008, 07:51 PM
  2. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 08:39 AM
  3. archive format
    By Nor in forum A Brief History of Cprogramming.com
    Replies: 0
    Last Post: 08-05-2003, 07:01 PM
  4. socket question
    By Unregistered in forum C Programming
    Replies: 3
    Last Post: 07-19-2002, 01:54 PM
  5. System
    By drdroid in forum C++ Programming
    Replies: 3
    Last Post: 06-28-2002, 10:12 PM