Find the answer to your Linux question:
Results 1 to 8 of 8
I am a amateur programmer in C/C++. I have been doing a small project that backup files on a client to a server. The platform I am working on in ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Mar 2003
    Location
    India
    Posts
    20

    a bug in my program


    I am a amateur programmer in C/C++. I have been doing a small project that backup files on a client to a server. The platform I am working on in Linux( redhat 8.0).
    I have finished writing this fairly simple program but I can't seem to get a bug out .
    The problem i think is with client.cpp but i will give you the list of programs involved. common.h, server.c and t.c

    Please help me out

    The common.h is common header file used by both client.cpp and server.c

    common.h
    Code:
    #ifndef COMMON_H
    #define COMMON_H
    enum Commands
    {
        NULL_VALUE,
        FILE_NAME,
        DATA,
        OK = 200
    };
    typedef struct __Head
    {
        enum Commands bType;
        unsigned int wSync;
        unsigned long dwSize;
    }HEAD, *PHEAD;
    
    char IP[16]="0.0.0.0";
    void* ReceiveData(void* pData);
    #endif

    client.cpp

    THIS IS WHERE I AM HAVING PROBLEM

    Code:
    #include <arpa/inet.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <time.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/stat.h>
    #include <netinet/in.h>
    #include <pthread.h>
    #include <unistd.h>
    #include "common.h"
    
    const char* CONFIG = "cfg.dat";
    extern char IP&#91;16&#93;;
    const int PORT = 1234;
    
    extern void* ReceiveData&#40;void* pData&#41;;
    int main&#40;&#41;
    &#123;
        int  sockfd;
        struct  sockaddr_in serv_addr;
        pthread_t pt;
        pthread_attr_t pat;
    
        bzero&#40;&#40;char *&#41; &serv_addr, sizeof&#40;serv_addr&#41;&#41;;
        serv_addr.sin_family=AF_INET;
        serv_addr.sin_addr.s_addr=inet_addr&#40;IP&#41;;
        serv_addr.sin_port=htons&#40;PORT&#41;;
    
        if&#40;&#40;sockfd=socket&#40;AF_INET,SOCK_STREAM, 0&#41;&#41; < 0&#41;
        &#123;
            printf&#40;"client&#58;can't open stream socket\r\n"&#41;;
            return 0;
        &#125;
        if &#40;&#58;&#58;connect&#40;sockfd, &#40;struct sockaddr *&#41; &serv_addr, sizeof&#40;serv_addr&#41;&#41; < 0&#41;
        &#123;
            printf&#40;"client&#58; can't connect to server\r\n"&#41;;
            return 0;
        &#125;
        pthread_attr_init&#40;&pat&#41;;
        pthread_create&#40;&pt, &pat, ReceiveData, &#40;void*&#41;sockfd&#41;;
        pthread_join&#40;pt, NULL&#41;;
    &#125;
    
    void* ReceiveData&#40;void* pData&#41;
    &#123;
        struct stat bstatbuff;
        char szFName&#91;32&#93;&#91;128&#93;;
        char szBuffer&#91;1024&#93;;
        char szFile&#91;128&#93;;
        char * pT;
    
        int client = &#40;int&#41;pData;
        int nRet, i = 0, nMax = 0;
        FILE *fp,*fs;
        unsigned long dwSize;
    
        HEAD head;
        printf&#40;"Entered thread\r\n"&#41;;
        fp = fopen&#40;CONFIG, "r+"&#41;;
        if&#40;NULL == fp&#41;
        &#123;
            printf&#40;"Error opening CONFIG FILE\r\n"&#41;;
            return NULL;
        &#125;
        memset&#40;szFile, 0, sizeof&#40;szFile&#41;&#41;;
        memset&#40;szFName, 0, sizeof&#40;szFName&#41;&#41;;
        while&#40;fread&#40;szFile, sizeof&#40;char&#41;, sizeof&#40;szFile&#41;,fp&#41;&#41;
        &#123;
            strcpy&#40;szFName, szFile&#41;;
            printf&#40;"Name -->%s\r\n",szFName&#41;;
            memset&#40;szFile, 0, sizeof&#40;szFile&#41;&#41;;
            i++;
            nMax = i;
        &#125;
        fclose&#40;fp&#41;;
        i = 0;
    
        for&#40; ;;&#41;
        &#123;
            if&#40;i >= nMax&#41;
            &#123;
                i = 0;
                printf&#40;"sleep 10 minute\r\n"&#41;;
                sleep&#40;10 * 60&#41;;
            &#125;
            printf&#40;"File Name --> %s\r\n", szFName&#41;;
            sleep&#40;1&#41;;
            //fflush&#40;fs&#41;;
            fs = fopen&#40;szFName, "rb"&#41;;
            if&#40;NULL == fs&#41;
            &#123;
                printf&#40;"error opening file %s\r\n",szFName&#41;;
                continue;
            &#125;
            memset&#40;szBuffer, 0, sizeof&#40;szBuffer&#41;&#41;;
    
            if&#40;stat&#40;szFName,&bstatbuff&#41; <  0&#41;
            printf&#40;"stat error" &#41;;
            dwSize = bstatbuff.st_size;
            memset&#40;&bstatbuff, 0, sizeof&#40;bstatbuff&#41;&#41;;
    
            printf&#40;"Total file size %ld\r\n",dwSize&#41;;
            pT = &#40;char*&#41;strrchr&#40;szFName, '/'&#41;;
            if&#40;!pT&#41;
            &#123;
                fclose&#40;fs&#41;;
                printf&#40;"error in file name%d\r\n"&#41;;
                continue;
            &#125;
            printf&#40;"FILE NAME %s len = %d\r\n",&#40;pT + 1&#41;, strlen&#40;&#40;pT + 1&#41;&#41;&#41;;
    
            memset&#40;&head, 0, sizeof&#40;head&#41;&#41;;
            head.bType = FILE_NAME;
            head.dwSize = strlen&#40;&#40;pT + 1&#41;&#41;;
            nRet = send&#40;client, &#40;char*&#41;&head,sizeof&#40;head&#41;,0&#41;;
            nRet = send&#40;client,&#40;pT+1&#41; , head.dwSize,0&#41;;
            /*if&#40;nRet < 0 || nRet == 0&#41;
            &#123;
                &#58;&#58;close&#40;client&#41;;
                return NULL;
            &#125;*/
            memset&#40;&head, 0, sizeof&#40;head&#41;&#41;;
    
            head.bType = DATA;
            head.dwSize = dwSize;
            nRet = send&#40;client,&#40;char*&#41;&head,sizeof&#40;head&#41;,0&#41;;
    
    
            rewind&#40;fs&#41;;
            memset&#40;szBuffer,0,sizeof&#40;szBuffer&#41;&#41;;
    
                while&#40;fread&#40;szBuffer,sizeof&#40;char&#41;, sizeof&#40;szBuffer&#41;, fs&#41;&#41;/* THIS IS WHERE I THINK THR PROBLEM IS*/
            &#123;
                printf&#40;"read data --> %s \r\n",szBuffer&#41;;
                nRet=send&#40;client,szBuffer,strlen&#40;szBuffer&#41;,0&#41;;
                /*if&#40;nRet < 0 || nRet == 0&#41;
                &#123;
                    &#58;&#58;close&#40;client&#41;;
                    return NULL;
                &#125;*/
                memset&#40;szBuffer,0,sizeof&#40;szBuffer&#41;&#41;;
            &#125;
            fclose&#40;fs&#41;;
            i++;
            printf&#40;"Sleep 2 sec\r\n"&#41;;
            sleep&#40;2&#41;;
        &#125;
        return NULL;
    &#125;
    The commented region is the part I am having problem with. Instead of reading 1024 bytes of data from the specified file it reads an previously read path “/root/jubin/test/client.cpp” from the config.dat file for example, at the almost end of 1024 bytes of read data. (hope u understood)
    And that’s what I get as a backup file ( the incomplete original file plus the path which is not part of the file) .

    server.c
    I don't think there is any problem with this program.

    Code:
    #include<stdio.h>
    #include<string.h>
    #include<sys/socket.h>
    #include<sys/types.h>
    #include<netinet/in.h>
    #include<arpa/inet.h>
    #include<pthread.h>
    #include "common.h"
    
    const int INVALID_SOCKET = 0;
    const int SOCKET_ERROR = -1;
    const int PORT = 1234;
    
    void* AcceptClient&#40;void* pD&#41;;
    void* ReceiveData&#40;void* pDa&#41;;
    int main&#40;&#41;
    &#123;
        int nSocket;
        struct sockaddr_in si;
        int nRet;
        pthread_t pt;
        pthread_attr_t pat;
    
        nSocket = socket&#40;AF_INET, SOCK_STREAM, 0&#41;;
        if&#40;INVALID_SOCKET == nSocket&#41;
        &#123;
            printf&#40;"Error creating socket\n"&#41;;
            return 1;
        &#125;
        si.sin_family=AF_INET;
        si.sin_port=htons&#40;PORT&#41;;
        si.sin_addr.s_addr=htonl&#40;INADDR_ANY&#41;;
        nRet = bind&#40;nSocket,&#40;struct sockaddr*&#41;&si, sizeof&#40;struct sockaddr_in&#41;&#41;;
        if&#40;SOCKET_ERROR == nRet&#41;
        &#123;
            printf&#40;"Error binding to socket\n"&#41;;
            return 1;
        &#125;
    
        nRet = listen&#40;nSocket, 5&#41;;
        if&#40;SOCKET_ERROR == nRet&#41;
        &#123;
            printf&#40;"Error listening to socket\n"&#41;;
        &#125;
        else
        &#123;
            printf&#40;"listening\r\n"&#41;;
        &#125;
        pthread_attr_init&#40;&pat&#41;;
        pthread_create&#40;&pt, &pat, AcceptClient, &#40;void*&#41;&nSocket&#41;;
        pthread_join&#40;pt,NULL&#41;;
    &#125;
    
    void* AcceptClient&#40;void* pD&#41;
    &#123;
        pthread_t pt;
        pthread_attr_t pat;
    
        int nServer = *&#40;int*&#41;pD;
        struct sockaddr_in sin;
        int nClient, nLen=sizeof&#40;sin&#41;;
         pthread_attr_init&#40;&pat&#41;;
        printf&#40;"thread created\r\n"&#41;;
        for&#40; ; ; &#41;
        &#123;
            nClient=accept&#40;nServer,&#40;struct sockaddr*&#41;&sin,&#40;socklen_t*&#41;&nLen&#41;;
    
            if &#40;INVALID_SOCKET == nClient&#41;
            &#123;
                printf&#40;"Error accepting client\n"&#41;;
                return NULL;
            &#125;
            else
            &#123;
                printf&#40;"Accepted client %s\r\n",
                        inet_ntoa&#40;sin.sin_addr&#41;&#41;;
                pthread_create&#40;&pt,&pat,ReceiveData,
                        &#40;void*&#41;&nClient&#41;;
            &#125;
        &#125;
    &#125;
    void* ReceiveData&#40;void* pD&#41;
    &#123;
        int nClient=*&#40;int*&#41;pD;
        int i;
        int nRet;
    
        unsigned char szBuff&#91;1024&#93;;
        unsigned char szFile&#91;512&#93;;
    
        unsigned long uPos = 0, dwRead, dwTotal, dwToRead;
    
        HEAD head;
        FILE* fp;
        for&#40;;;&#41;
        &#123;
            memset&#40;&head, 0, sizeof&#40;head&#41;&#41;;
            memset&#40;szBuff,0,sizeof&#40;szBuff&#41;&#41;;
    
            nRet=recv&#40;nClient,&#40;char*&#41;&head,sizeof&#40;head&#41;,0&#41;;
            if&#40;-1 == nRet || 0 == nRet&#41;
            &#123;
                printf&#40;"Error receiving header\r\n"&#41;;
                shutdown&#40;&#40;int&#41;nClient,2&#41;;
                close&#40;nClient&#41;;
                return NULL;
            &#125;
            else
            &#123;
                switch&#40;head.bType&#41;
                &#123;
                case FILE_NAME&#58;
                    dwTotal = head.dwSize;
                    printf&#40;"Total size %ld\r\n",dwTotal&#41;;
                    dwRead = 0;
                    memset&#40;szBuff,0,sizeof&#40;szBuff&#41;&#41;;
                        do
                    &#123;
                        dwToRead = &#40;&#40;dwTotal - dwRead&#41; > sizeof&#40;szBuff&#41;&#41; ?
                            sizeof&#40;szBuff&#41; &#58; &#40;dwTotal - dwRead&#41;;
                        nRet=recv&#40;nClient,&#40;char*&#41;&szBuff&#91;dwRead&#93;, dwToRead,0&#41;;
                        if&#40;nRet > 0&#41;
                        &#123;
                            dwRead += nRet;
                            printf&#40;"rcv ->%d\r\n",nRet&#41;;
                        &#125;
                    &#125;
                    while&#40;dwRead < dwTotal&#41;;
    
                    memset&#40;szFile,0,sizeof&#40;szFile&#41;&#41;;
                    sprintf&#40;szFile, "/backup/%s",szBuff&#41;;
                    printf&#40;"Name %s\r\n",szFile&#41;;
                    fp = fopen&#40;szFile, "ab+"&#41;;
                    if&#40;NULL == fp&#41;
                    &#123;
                        fp = fopen&#40;szFile, "wb+"&#41;;
                    &#125;
                    //uPos = 0;
                    fclose&#40;fp&#41;;
                    break;
                case DATA&#58;
                    dwTotal = head.dwSize;
                    printf&#40;"Total size of %s-->%ld\r\n",szFile,dwTotal&#41;;
                    dwRead = 0;
                    fp = fopen&#40;szFile, "rb+"&#41;;
                        do
                    &#123;
                        dwToRead = &#40;&#40;dwTotal - dwRead&#41; > sizeof&#40;szBuff&#41;&#41; ?
                            sizeof&#40;szBuff&#41; &#58; &#40;dwTotal - dwRead&#41;;
                        memset&#40;szBuff,0,sizeof&#40;szBuff&#41;&#41;;
                        nRet=recv&#40;nClient,&#40;char*&#41;szBuff, dwToRead,0&#41;;
                        if&#40;nRet > 0&#41;
                        &#123;
                            dwRead += nRet;
                            printf&#40;"rcv ->%d\r\n",nRet&#41;;
                            if&#40;NULL != fp&#41;
                            &#123;
                                fwrite&#40;szBuff,sizeof&#40;char&#41;,nRet,fp&#41;;
                            &#125;
                            printf&#40;"wrote ->%d\r\n",nRet&#41;;
                        &#125;
                    &#125;
                    while&#40;dwRead < dwTotal&#41;;
                    if&#40;NULL != fp&#41;
                    &#123;
                        fclose&#40;fp&#41;;
                    &#125;
                    break;
                &#125;
            &#125;
        &#125;
    &#125;
    The following program is used to create the config.dat file from where client.cpp reads the file to be backed up

    t.c

    Code:
    #include<stdio.h>
    
    main&#40;&#41;
    &#123;
        FILE* fP;
        char szData&#91;128&#93;;
            int ch;
        printf&#40;"Enter append mode 1 for yes &#58;"&#41;;
        scanf&#40;"%d",&ch&#41;;
        if&#40;1 == ch&#41;
        &#123;
            fP = fopen&#40;"cfg.dat", "ab"&#41;;
        &#125;
        else
        &#123;
            fP = fopen&#40;"cfg.dat", "wb"&#41;;
        &#125;
        if&#40;NULL == fP&#41;
        &#123;
            printf&#40;"Error opening file\r\n"&#41;;
            return 1;
        &#125;
        do
        &#123;
            memset&#40;szData, 0, sizeof&#40;szData&#41;&#41;;
            printf&#40;"Enter filename with full path &#58;"&#41;;
            fflush&#40;stdin&#41;;
            scanf&#40;"%s",szData&#41;;
            if&#40;0 < strlen&#40;szData&#41;&#41;
            &#123;
                printf&#40;"Data-->%s\r\n",szData&#41;;
                     fwrite&#40;szData,sizeof&#40;char&#41;,sizeof&#40;szData&#41;, fP&#41;;
            &#125;
            printf&#40;"Continue .. -1 to exit"&#41;;
            fflush&#40;stdin&#41;;
            scanf&#40;"%d",&ch&#41;;
        &#125;
        while&#40;-1 != ch&#41;;
        fclose&#40;fP&#41;;
    &#125;
    ****I WOULD BE GRATEFUL FOR ANY HELP***

  2. #2
    Linux Guru
    Join Date
    Oct 2001
    Location
    Täby, Sweden
    Posts
    7,578
    The problem is quite simple, in fact. It is where you expected. You're checking for the received length of the data from fread with strlen, while in fact it isn't a string.

    C strings are special cases of arrays of bytes. The string is stored first, and then a NUL character is stored to terminate the string. fread doesn't read strings, however, it only reads arrays of bytes, and it doesn't NUL terminate them (you'll also have a problem if there is a NUL byte in the file that you read). fread returns the number of characters (not bytes, though, but the number of "units" that you specifiy as its second argument) that it read from the file as its return value, so you should use that as authoritative instead of using strlen. See the manpage for fread for more detailed info.

    Also, if you don't mind me asking, why have you made the client program multithreaded, and why have you named it .cpp when you only use pure C features?

  3. #3
    Just Joined!
    Join Date
    Mar 2003
    Location
    India
    Posts
    20
    I can't believe it was so simple. I spent over three days over that problem and once u told me how it works i solved it in 10 minutes,

    Thanks Dolda2000 Iam very grateful.

    I saved the program in "cpp" cause i am also planning to create an interface using QT. Since QT is written in cpp i thought it would be better to save it in cpp (is there anything wrong). I am very bad at QT. would you help me out with it? Its just in its begining stages and there is a lot of cleaning up to do.

    About fread: I did another program using fread and send the way i showed above and it works with out any probs, y is that??

  4. #4
    Linux Guru
    Join Date
    Oct 2001
    Location
    Täby, Sweden
    Posts
    7,578
    About fread: It was very probably by chance, such as that you happened to be reading into a NUL-initialized buffer or anything. While it is true that you have a memset line before the fread call in this program, the fread call is part of a loop and thus the next time in the loop that it is called, memset will not have been run on the buffer. So, I suspect that it was because you ran memset on it first.
    Note though, that it's not a good solution to rely on memset. If fread reads any NULs from the file, you won't see all the data if you use the str* functions.

    As for QT, I don't have any experience of it, mainly since I despise C++ (in a respectful manner, of course =) ). I you ask me, I would suggest you to use GTK2 instead. There's a great tutorial on that on http://www.gtk.org/.

    Some recommendations for programming:
    Have you tried GDB? It's a great way of finding out what's wrong with a program, especially if you use it from the world's best text editor - GNU EMACS.
    As stated above: GNU EMACS. I have no words for it; it's simply best.
    Also, Valgrind is a truly great program for finding potential errors in a program. One of the best I've ever tried, in fact.

    When I code, I use these three more or less constantly, GNU EMACS literally constantly. It has improved the quality of my code a thousandfold.

  5. #5
    Just Joined!
    Join Date
    Mar 2003
    Location
    India
    Posts
    20
    I learned to write my first program in C++; but I am not good enough to tell which is better. Isn't OOP the best way to program mainly because designing in objects help in writing code more quickly.

    I have never heard of GDB or valgrind can one, download it from any site.
    I use Emacs too, but the font size is too small. Is there any way increasing the font size? ( my eyes hurt after staring at it for too long).

    I heard coding in QT is portable to windows. And if you have "Desinger"
    its something like VB using C++, you only have to know the code if you want to do something serious.

    Also do you know how to compile java in linux; or if java is installed.

  6. #6
    Linux Guru
    Join Date
    Oct 2001
    Location
    Täby, Sweden
    Posts
    7,578
    Hmm, there are several ways of increasing the font size in emacs. You can, for example, try running this:
    Code:
    xrdb -merge
    emacs*font&#58; 7x13
    &#40;Type Ctrl+D here to stop processing&#41;
    GDB probably comes with your system; it usually does. Just type gdb to start it. It can be a bit frustrating to use from a terminal, though, but emacs has a nice interface to it. Type M-x gud RET to start it.

    I'm fairly sure that GTK has been ported to Windoze as well; I have seen pictures of it, at least, but I haven't really cared since I don't care for Windoze. =)
    As for that Designer thing, I'm fairly sure that it's about the same thing as Glade for GTK. Glade also usually comes with the system.

    FYI, QT is the primary toolkit for KDE programs, while GTK is the primary one for GNOME programs.

    To program in Java, you need to download the JDK from java.sun.com. Unfortunately, there is not yet a free Java VM.

  7. #7
    Just Joined!
    Join Date
    Mar 2003
    Location
    India
    Posts
    20
    I got a problem ..
    Supposing i created two different threads how do i terminate only one of them . what would be the code to termiate a thread.

    Also i tried the following code to increase the font size of emacs but got no result.
    Code:
    xrdb -merge 
    emacs*font&#58; 7x13 
    &#40;Type Ctrl+D here to stop processing&#41;

  8. #8
    Linux Guru
    Join Date
    Oct 2001
    Location
    Täby, Sweden
    Posts
    7,578
    To make a thread terminate itself, make it call pthread_exit. To terminate another thread, call pthread_cancel with the pthread_t data as the argument.

    As for emacs, try to run "emacs -font 7x13" to see if you have that font.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •