2013-03-28 42 views
-1

在我的客戶端 - 服務器應用程序中發生了一些奇怪的事情。請看看這些簡單的叉的客戶機/服務器: 客戶:不終止的進程

#include <sys/types.h> 
#include <sys/socket.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <time.h> 
#include <arpa/inet.h> 
#include <string.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <sys/ioctl.h> 
#include <sys/time.h> 
#include <errno.h> 
#include <sys/time.h> 
#include <sys/wait.h> 


#define IP_SERVER "192.168.1.89" 
#define PORT_SERVER 65000 
#define BUFFERSIZE 1024 
#define NUMFILES 3 


double timeElapsed(struct timeval* before, struct timeval* after) { 

    return after->tv_sec - before->tv_sec + (double) (after->tv_usec - before->tv_usec)/1000000; 
} 


void getFile(char *request, struct sockaddr_in server) { 

    char buffer[1024]; 
    int sockProc, res; 
    int file; 
    int sizeServ = sizeof(server); 
    int writeFile; 

    sockProc = socket(AF_INET, SOCK_STREAM, 0); 

    if (sockProc < 0) { 
     printf("Error on creating socket client\n"); 
     perror(""); 
     exit(1); 
    } 

    file = open(request, O_CREAT | O_WRONLY, S_IRWXU); 


    res = connect(sockProc, (struct sockaddr*)&server, (socklen_t)sizeServ); 
    if (res < 0) { 
     printf("Error on connecting to server!\n"); 
     perror(""); 
     exit(1); 
    } 

    res = send(sockProc, (void*)request, strlen(request), 0); 

    memset(buffer, 0, sizeof(buffer)); 

    while((res = recv(sockProc, (void*)buffer, sizeof(buffer), 0)) > 0) { 
     write(file, (void*)buffer, strlen(buffer)); 
     memset(buffer, 0, sizeof(buffer)); 
    } 


    close(sockProc); 
    close(file); 
    return; 

    } 


    int main(int argc, char** argv) { 

    int sockCli, res, i; 

    struct sockaddr_in server; 
    int sizeServ = sizeof(server); 
    memset(&server, 0, sizeof(server)); 
    server.sin_family = AF_INET; 
    inet_pton(AF_INET, IP_SERVER, &server.sin_addr); 
    server.sin_port = htons(PORT_SERVER); 

    char files[NUMFILES][32]; 
    char nameFile[32]; 

    char command[32] = "rm *.txt"; 

    system(command); 

    struct timeval begin; 
    struct timeval end; 

    pid_t processes[NUMFILES]; 



    for(i = 0; i<NUMFILES; i++) { 

     memset(nameFile, 0, sizeof(nameFile)); 
     printf("Inserisci nome file (con estensione) da ricevere:\n"); 
     scanf("%s", nameFile); 
     strcpy(files[i], nameFile); 

    } 


    gettimeofday(&begin, NULL); 

    for(i=0; i<NUMFILES; i++) { 

     pid_t child = fork(); 

     if(child == 0) { 
      getFile(files[i], server); 
      exit(0); 
     } 

     else { 
      processes[i] = child; 
      continue; 
     } 

    } 


    /*for(i=0; i<NUMFILES; i++) { 
     waitpid(processes[i], NULL, 0); 
    }*/ 

    wait(NULL); 

    gettimeofday(&end, NULL); 
    printf("Time elapsed on TCP is %f seconds\n", timeElapsed(&begin, &end)); 
    return 0; 

    } 

和服務器:

#include <sys/socket.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <time.h> 
#include <arpa/inet.h> 
#include <string.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <sys/ioctl.h> 
#include <sys/stat.h> 

#define IP_SERVER "192.168.1.89" 
#define PORT_SERVER 65000 
#define BUFFERSIZE 1024 

void execRequest(int* sockCli, struct sockaddr_in* client) { 

    char buffer[BUFFERSIZE]; 
    char request[BUFFERSIZE]; 
    int res; 

    memset(request, 0, sizeof(request)); 

    res = recv(*sockCli, (void*)request, sizeof(request), 0); 

    if(res < 0) { 
     printf("Error on recv()\n"); 
     perror(""); 
     exit(1); 
    } 
    printf("Requested file %s\n", request); 

    char resource[32] = "files/"; 
    strcat(resource, request); 

    int file = open(resource, O_RDONLY); 

    if (file < 0) { 
     printf("File %s does not exist\n", request); 
     exit(1); 
    } 

    memset(buffer, 0, sizeof(buffer)); 

    while((res = read(file, (void*)buffer, sizeof(buffer))) > 0) { 
     send(*sockCli, (void*)buffer, strlen(buffer), 0); 
     memset(buffer, 0, sizeof(buffer)); 
    } 

    close((*sockCli)); 
    close(file); 
    free(sockCli); 
    free(client); 

    return; 

    } 

int main(int argc, char** argv) { 

    int sockServ, i, res; 
    int *sockCli; 

    struct sockaddr_in server; 
    struct sockaddr_in* client; 


    sockServ = socket(AF_INET, SOCK_STREAM, 0); 

    if(sockServ < 0) { 
     printf("Error in creating socket\n"); 
     perror(""); 
     exit(1); 
    } 

    memset(&server, 0, sizeof(server)); 
    server.sin_addr.s_addr = inet_addr(IP_SERVER); 
    server.sin_port = htons(PORT_SERVER); 
    server.sin_family = AF_INET; 

    int reuse = 1; 
    res = setsockopt(sockServ, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)); 
    if (res < 0) { 
     printf("setsockopt() REUSEADDR failed\n"); 
     perror(""); 
     exit(1); 
    } 

    res = bind(sockServ, (struct sockaddr*)&server, sizeof(server)); 
    if (res < 0) { 
     printf("Error on bindind TCP server!\n"); 
     perror(""); 
     exit(1); 
    } 

    res = listen(sockServ, 5); 
    if (res < 0) { 
     printf("Error on listening TCP server!\n"); 
     perror(""); 
     exit(1); 
    } 

    while(1) { 

     sockCli = (int*)malloc(sizeof(int)); 
     client = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in)); 
     int sizeClient = sizeof(struct sockaddr_in); 

     *sockCli = accept(sockServ, (struct sockaddr*)client, &sizeClient); 

     if ((*sockCli) < 0) { 
       printf("accept() failed\n"); 
     perror(""); 
     continue; 
     } 

     printf("Connected to %s:%d\n", inet_ntoa(client->sin_addr), client->sin_port); 

     if(!fork()) { 

      execRequest(sockCli, client); 
      exit(0); 

     } 

     else 
      continue; 



} 

    return 0; 


    } 

這是很奇怪的。即使服務器關閉套接字,客戶端創建的進程也不會終止,因此recv()應返回0並讓客戶端進程退出循環。此外,讀取文件有些奇怪: 服務器只是讀取files.txt文件,但是在讀取文件時包含字符串「.txt」,並將所有這些混合文件發送給客戶端...爲什麼? 它們就像 aaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaa

但服務器簡單的文件單字符讀取和發送:

aaaaaaaaaaaaaaaaaa.txt aaaaaaaaaaaaaaaaaa

我可以解決這一切?

+1

您是否在Linux上使用了像gdb這樣的調試器?你是否編譯過所有的警告和調試信息,例如'gcc -Wall -g'? –

+1

如果你想讓我們讀你的代碼,請使它可讀...一致的空白/ tabb會很好。 – Sebivor

回答

1

您不能使用strlen(buffer),僅僅因爲您正在從文本文件加載字符並不意味着buffer將是一個有效的字符串,除非您採取措施確保它是。你不知道;由於您可以使用文件中的所有數據填充buffer,因此不會終止。

+0

那麼,我該如何完成?該文件可以是任意長... – user2204592

+0

我看到的問題是,如果服務器monoprocess一切完成...而是使用fork()創建過程它不...有什麼區別? – user2204592

+0

放鬆說的是不正確的。當沒有更多內容要讀取時,即使緩衝區未完全填滿,從文件讀取也會停止。實際上服務器進程關閉連接,但它證明客戶端進程沒有看到它...... – user2204592

0

在堆棧溢出時,我們必須在這裏播放損壞的記錄多少次? Don't cast malloc

我粉筆這個錯誤讀取故障手冊中的,找出什麼頭包括一個字符串是什麼(因此什麼的strlen/strcat的/ STR * {任何} *期待其輸入,printf期望的對應於%s格式說明符的參數等)和什麼是read/recv產生

res = recv(*sockCli, (void*)request, sizeof(request), 0); 
if(res < 0) { 
    printf("Error on recv()\n"); 
    perror(""); 
    exit(1); 
} 
printf("Requested file %.*s\n", res, request); // NOTE the field width provided by 'res' 

通過手動,實例如res = read(file, (void*)buffer, sizeof(buffer))理應存儲任一錯誤或長度。該條件確保send代碼僅在長度爲值時纔會執行,那麼爲什麼不將它作爲一個使用呢? send(*sockCli, (void*)buffer, res, 0);

這些問題的存在似乎表明你的學習方法不起作用。你在讀哪本書?沒有書的情況下學習C有點像學習沒有交流的情況下哪些漿果是有毒的。

+0

好吧,我解決了一些問題,這要感謝你所說的......現在我在send()調用中使用res,並且收到的文件不再有「.txt」...但客戶端仍然不停止。我不承認爲什麼那個該死的recv()在客戶端進程dosn't返回0時,套接字關閉! :(+ – user2204592

+0

ps:我想我知道C ...我用C編寫了3個項目,即使是一個簡單的內核unix作爲操作系統項目,但我認爲我忘記了如何使用一些系統調用... – user2204592

+0

@ user2204592那麼,你已經展示了閱讀和理解手冊的能力,你已經證明不能閱讀和理解我的問題,這是一種閱讀障礙還是一種理解障礙?如果它是一種閱讀障礙,或許你可以使用你在stackoverflow上使用的任何機制來將手冊轉化爲你能理解的東西如果它是一種理解障礙,你真的不應該成爲程序員... – Sebivor