Thread: sending binaries files between server and client

  1. #1
    Registered User
    Join Date
    Nov 2006
    Location
    japan
    Posts
    126

    sending binaries files between server and client

    I wrote this 2 funcions in order to send and receive files using a file descriptors
    ******SOME COMMENTS ARE IN JAPANESE***

    Code:
    /*myFunc.h*/
    
    #ifndef BUFSIZE
    	#define BUFISIZE 256
    #endif
    
    	
    void receive_file_from(int fd, char *fileName)
    { 
    	/*fd :ファイル記述子*/
        char		buf[BUFSIZE];		/* ファイルの内容を格納するバッファ */ 
       	FILE		*fp;				/* 受信ファイルポインター */
    	ssize_t		br;					/* read()で読み込んだバイト数 (bites readの略)*/
    	
    	/* 書き込みモードでファイルを開く */
    	printf("\nopening file '%d'\n", fileName); 
    	if( (fp = fopen(fileName, "w"))==NULL){ 
    		perror("fopen");
    		exit(1); 
    	} 
    	
    	/* ファイルデータの受信とコーカルファイルへの書き込み */ 
    	printf("writing file received from the %d\n", fd);
    	while( ( br = read(fd, buf, BUFSIZE) )>0){ 
    		//printf("%s\n", buf);  //ファイル内容を表示
    		fwrite(buf,sizeof(char),br,fp);
    	}
    	
    	/*ファイルデータの受信の終了*/
    	printf("file was successfully received and saved as %s\n", fileName);
    
    	fclose(fp); //corrected
    
    }
    
    void send_file_to(int fd, char* fileName){
    	
    	char		*buf[BUFSIZE];		/* ファイルの内容を格納するバッファ */
    	FILE		*fp;				/* 送信ファイルポインタ */
    	size_t		br;					/* read()で読み込んだバイト数 (bites readの略)*/
    	
    	/* 読み込みモードでファイルを開く */
    	printf("\nopening file '%d'\n", fileName); 
    	if( (fp = fopen(fileName, "r") )== NULL ){
    		perror("fopen");
    		exit(1);
    	}
    	/* ローカルファイルデータの読み込みと送信 */
    	printf("reading local file and sending to %d\n", fd);
    	while( ( br = fread(buf,sizeof(char),BUFSIZE,fp) )>0){
    		write(fd, buf, br); 
    		//printf("%s\n", buf);	//ファイル内容を表示
    	}
    	
    	/*ファイルデータの送信の終了*/
    	printf("file was successfully read and sent\n");
    	fclose(fp); //corrected
    }
    I call them from the server and client program in order to receive a file (lets say the file is image.txt and is in the same place as client program )from the client to the server and everything goes great. But my problem is when i try to send back the same file (with a different file name) to the client from the server. It seems that write() system call is not completely correct. I mean, when i try to do the 2 operations the file is not even correctly received (from the client to the server). I suspect there is a problem of synchronization... maybe? I cannot think of another think, but still if is synchronization, i don't know how to do it.
    Can any one help me?

    my server program is as follows.:

    Code:
    /* システムプログラミング 並行サーバの実現 (concurrent_server.c)  */ 
    #include    <stdio.h> 
    #include    <sys/types.h> 
    #include    <sys/socket.h> 
    #include    <netinet/in.h> 
    #include    <sys/stat.h> 
    #include    <fcntl.h> 
    #include	<stdlib.h>
    #include	<strings.h>
    
    #define     BUFSIZE 256 /* バッファサイズ */ 
    
    #include	"../myFuncs.h"
    
    #define     ERR -1 /* システムコールのエラー */ 
    #define     SERVER_PORT 50000 /* サーバのソケットの名前(ポート番号) */ 
    
    main(int argc, char *argv[]) 
    { 
        int                 sockfd;		/* socket()の返すファイル記述子 */ 
        int                 ns;			/* accept()の返すファイル記述子 */ 
        struct  sockaddr_in server;		/* サーバプロセスのソケットアドレス情報 */ 
        struct  sockaddr_in client;		/* クライアントプロセスのソケットアドレス 情報 */ 
        socklen_t           fromlen;	/* クライアントプロセスのソケットアドレス 情報の長さ */ 
        int                 pid;		/* プロセスID */ 
    	FILE				*fp;
    	char				*tempFileName; /* 一時的なファイルの名前 */
    	
        if(argc != 1){ /* コマンドの引数が正しく与えられなかった場合 */ 
    		printf("Usage: concurrent_server\n"); 
    	} 
    	
    	if( (sockfd = socket(PF_INET, SOCK_STREAM, 0)) == ERR) {/* ソケットの作成 */ 
            perror("server: socket"); 
            exit(1); 
        } 
       
        bzero((char *)&server, sizeof(server)); /* アドレス情報構造体 の初期化 */ 
        server.sin_family      = PF_INET; /* プロトコルファミリの設定 */ 
        server.sin_port        = htons(SERVER_PORT); /* ソケットの名前(ポート番号)の設定 */ 
        server.sin_addr.s_addr = htonl(INADDR_ANY); /* IPアドレスの設定 */
    	
    	printf("\tINADDR_ANY: %X\n\tserver.sinaddr.s_addr: %X\n",INADDR_ANY, server.sin_addr.s_addr);
    
        if( bind(sockfd, (struct sockaddr *)&server, sizeof(server)) == ERR) { 
    		perror("server: bind"); 
            exit(1); 
        } 
    	
    	if( listen(sockfd, 5) == ERR) { /* 接続要求の受け入れ準備 */ 
            perror("server: listen"); 
            exit(1); 
        } 
    	
        while(1) { /* 永久ループ */ 
    		
    		fromlen = sizeof(client); 
            if( (ns = accept(sockfd, (struct sockaddr *)&client, &fromlen)) == ERR ) { /* 接続要求の許可 */ 
                perror("server: accept"); 
                exit(1); 
            } 
    		
    		printf("\nconnect request from: %s   port: %d\n", 
    			   inet_ntoa(client.sin_addr), ntohs(client.sin_port)); 
            if( (pid = fork()) == 0 ) { /* fork process */ 
                /* child process */ 
    			strcpy(tempFileName,"temporal.txt");
                            receive_file_from(ns, tempFileName); /* receiving file from client as tempFileName */ 
    			sleep(3);
                             //execute(tempFileName, option);	/* not implemented yet*/
    			//send_file_to(ns, tempFileName);	/* sends back file to the client  THIS IS THE PROBLEM*/
    			
    			close(ns); /* accept()で返されたファイル記述子のクローズ */ 
                close(sockfd); /* socket()で返されたファイル記述子のクローズ */ 
                exit(0); /* 正常終了 */ 
            } 
            else if( pid >= 1 ) 
    		/* parent process */ 
                close(ns); /* accept()で返されたファイル記述子のクローズ */ 
            else { 
    			perror("server: fork"); 
    			exit(1); 
            } 
        } 
        close(sockfd);  
        exit(0); 
    }
    and the client program is as follows :

    Code:
    #include    <stdio.h> 
    #include    <sys/types.h> 
    #include    <sys/socket.h> 
    #include    <netinet/in.h> 
    #include    <netdb.h> 
    #include	<strings.h>
    #include	<stdlib.h>
    
    
    #define     BUFSIZE     256 /* バッファサイズ */ 
    
    #include	"../myFuncs.h"
    
    #define     ERR         -1 /* システムコールのエラー */ 
    #define     SERVER_PORT 50000 /* サーバのソケットの名前(ポート番号) */ 
    void        usage(void); /* Usageメッセージの出力 */ 
    char        *command_name; /* コマンド名 */ 
    
    main(int argc, char *argv[]) 
    { 
        int                 sockfd; /* socket()の返すファイル記述子 */ 
        struct  sockaddr_in server; /* サーバプロセスのソケットアドレス情報 */ 
        struct  hostent     *hp; /* ホスト情報 */ 
        char                buf[BUFSIZE]; /* メッセージを格納するバッファ */ 
        int                 n; /* 受信バイト数 */ 
        int                 fnamelen; /* メッセージ長 */ 
        char				*rindex(const char *s, int c); /* 末尾から文字列検索 */ 
    	char				*hostname;
    	int status;
    	
        if((command_name = rindex(argv[0], '/')) != NULL) /* コマンド名の獲得 */ 
            command_name++; 
        else 
            command_name = argv[0]; 
        
    	/*
    	*	argv[0] = client_kadai_func
    	*	argv[1] = hostname (get the hostname by typing hostname in the UNIX command line )
    	*/
    	
    	if(argc != 2) {/*  check arguments */ 
            fprintf(stderr,"Usage: %s server-hostname\n", command_name); 
    		exit(1); 
    	}
    	
    	hostname = argv[1];
    	if(	strcmp(argv[1],"local") == 0)
    		if(gethostname(hostname, sizeof(hostname)+1)==ERR){
    			perror("client: gethostname");
    			exit(1);
    		}
    	printf("connection (hostname): %s\n",hostname);
    	
    	if( (sockfd = socket(PF_INET, SOCK_STREAM, 0)) == ERR) {/* ソケットの作成 */ 
            perror("client: socket"); 
            exit(1); 
        } 
        
    	bzero((char *)&server, sizeof(server));		/* アドレス情報構造体の初期化 */ 
        server.sin_family = PF_INET;				/* プロトコルファミリの設定 */ 
        server.sin_port   = htons(SERVER_PORT);		/* ソケットの名前(ポート番号)の設定 */ 
        
    	if( (hp = gethostbyname(argv[1])) == NULL) { /* ホスト情報の獲得 */ 
            herror("client: gethostbyname");
            exit(1); 
        }
    		 
        bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length); 
        
    	if( connect(sockfd, (struct sockaddr *)&server, sizeof(server)) == ERR){ 
    		perror("client: connect"); 
            exit(1); 
        } 
    	
    	send_file_to(sockfd, "image.txt");
    	sleep(3);
    	//receive_file_from(sockfd, "receivedFromServer.txt"); /*THIS IS THE PROBLEM!!*/
    	
    	close(sockfd);  
        exit(0); 
    	
    }
    Last edited by nacho4d; 01-29-2008 at 04:52 AM. Reason: some unneeded coments
    Mac OS 10.6 Snow Leopard : Darwin

  2. #2
    Registered User
    Join Date
    Nov 2006
    Location
    japan
    Posts
    126
    I just realized one possible error:

    instead close(fp) it should be fclose(fp)
    I wonder why my gcc compiler doesn't say anything....
    Mac OS 10.6 Snow Leopard : Darwin

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    And it seems your code is in need of some indentation help:
    http://cpwiki.sf.net/User:Elysia/Indentation
    Remember: Indentation makes your code readable.
    Consider using better variable names such as br should be "bytesread".

    I also note more problems.
    Your code uses fp, but it's neither global nor passed to the functions, so how can they actually use the fp variable?
    Winsock functions uses SOCKET, not int. Further, recv and send are used with winsock and not read/write. I haven't done winsock programming before, though, so I don't know if it's right or not, but I definitely don't suggest using read/write for this.
    Last edited by Elysia; 01-29-2008 at 04:22 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    > I wonder why my gcc compiler doesn't say anything....
    Try compiling with -Wall

    You should see something like, "warning: assignment makes integer from pointer without a cast"
    Last edited by zacs7; 01-29-2008 at 04:27 AM.

  5. #5
    Registered User
    Join Date
    Nov 2006
    Location
    japan
    Posts
    126
    I open with fopen() in order to have the file pointer fp. (which is a local file)
    I use write() to write the content of the file to a file descriptor (for example fd), which is "linked" with the other program. Is not I am writing the file directly.

    I want to :
    read the local file(client)
    pass its contents to the server(client)
    receive the file content (server)
    do something with the file (server). (some kind of image processing, but this function is not implemented yet)
    and after doing that i want to send back the new file to the client(server)
    receive the content of the file (client)
    everything has to be binary since I am trying to pass an image file.
    and regarding the indentation, sorry elysia, but when i pasted everything turned a mess...
    Mac OS 10.6 Snow Leopard : Darwin

  6. #6
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    You should be explicit about being in binary mode too,

    Code:
    fopen(filename, "wb");

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Oh, right. You're mixing spaces and tabs. Use one and it'll be fine, you'll see
    How about using recv and send instead?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Nov 2006
    Location
    japan
    Posts
    126
    Quote Originally Posted by Elysia View Post
    How about using recv and send instead?
    what are the differences between recv and read? and send and write? what advantages to I have if I use them?
    Mac OS 10.6 Snow Leopard : Darwin

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    send/recv is for Winsock programming, open/write is for file writing (local file system).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Registered User
    Join Date
    Nov 2006
    Location
    japan
    Posts
    126
    I am afraid I should not use them (or cannot use them) because I am at Darwin, Mac OS X unix terminal, ...
    Mac OS 10.6 Snow Leopard : Darwin

  11. #11
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    If you're trying to write the program for a reason and not because you have to, consider using 'scp' (do a man scp) to copy/transport the file, otherwise use sockets.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    One thing that you need to consider is that write / send can be partially successful, in that only part of the data you want to send will be transmitted.

    Code:
    void sendAblock ( unsigned char *data, size_t len ) {
      while ( len > 0 ) {
        int amount = write ( fd, data, len );
        if ( amount > 0 ) {
          len -= (size_t)amount;    // reduce the amount left to send
          data += amount;           // advance the buffer
        } else {
          // something else 0 is closed, -1 is error
        }
      }
    }
    The same is also true for read/recv as well. Don't assume that if something sends you 10 bytes in a single send that you'll be able to read just those 10 bytes in a single read/recv at the other end. Fragmentation and reassembly are all part of the deal when dealing with socket streams.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Code:
    strcpy(tempFileName,"temporal.txt");
    receive_file_from(ns, tempFileName); /* receiving file from client as tempFileName */ 
    sleep(3);
    //execute(tempFileName, option);    /* not implemented yet*/
    //send_file_to(ns, tempFileName);    /* sends back file to the client  THIS IS THE PROBLEM*/
    tempFileName is an UNINITIALISED pointer.
    Who knows what it trashes, or when the damage will finally be noticed.

    char *tempFileName = "temporal.txt";
    and remove the strcpy would be just as good.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Client/server problem; server either stops receiving data or client stops sending
    By robot-ic in forum Networking/Device Communication
    Replies: 10
    Last Post: 02-16-2009, 11:45 AM
  2. Replies: 2
    Last Post: 07-24-2008, 06:05 AM
  3. Replies: 2
    Last Post: 11-23-2007, 02:10 AM
  4. Where's the EPIPE signal?
    By marc.andrysco in forum Networking/Device Communication
    Replies: 0
    Last Post: 12-23-2006, 08:04 PM
  5. Unicode vurses Non Unicode client server application with winsock2 query?
    By dp_76 in forum Networking/Device Communication
    Replies: 0
    Last Post: 05-16-2005, 07:26 AM