簡體   English   中英

為什么當我聲明一個 int 變量時,我的應用程序會凍結? C程序

[英]why when I declare an int variable my aplication freezes? C program

到目前為止,這是我的服務器代碼:一個 function 查找文件中是否存在單詞:

int Search_in_File_name(char *fname, char *str) {
    FILE *fp;
    int line_num = 1;
    int find_result = 0;
    char temp[512];
    if((fp = fopen(fname, "r")) == NULL) {
        return(-1);
    }


    while(fgets(temp, 512, fp) != NULL) {
        if((strstr(temp, str)) != NULL) {
            //printf("\n[copil] logare reusita");
            find_result++;
        }
        line_num++;
    }

    if(find_result == 0) {
        //printf("\nnume incorect");
        fclose(fp);
        return(3);
    }
    
    //Close the file if still open.
    if(fp) {
        fclose(fp);
    }
    return(4);
}

在做其他事情之前,我必須查看客戶端是否登錄。 我對連接到服務器的每個客戶端都使用了 fork。 我想在我的項目目錄中為每個客戶端創建一個文件,我需要客戶端的編號來執行此操作(或“ntohs(newAddr.sin_port)”指定的端口,但我無法獲得客戶端的編號,因為我不能聲明任何 int 變量。

int main(){

    int sockfd, ret;
    struct sockaddr_in serverAddr;

    int newSocket;
    struct sockaddr_in newAddr;

    socklen_t addr_size;

    char buffer[1024];
    pid_t childpid;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0){
        printf("[-]Error in connection.\n");
        exit(1);
    }
    printf("[+]Server Socket is created.\n");

    memset(&serverAddr, '\0', sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(PORT);
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));  //asociaza adresa serverAddr(localhost) la socketul creat (sockfd)
    if(ret < 0){
        printf("[-]Error in binding.\n");
        exit(1);
    }
    printf("[+]Bind to port %d\n", PORT);

    if(listen(sockfd, 10) == 0){ //marcheaza socketul (sockfd) ca fiind socketul care va accepta o conexiune viitoare si limita maxima de conexiuni in asteptare 
        printf("[+]Listening....\n");
    }else{
        printf("[-]Error in binding.\n");
    }

    while(1){
        newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size); //ia prima conexiune din lista asociata lui sockfd prin listen si creaza un nou socket si returneaza un descriptor de fisier pentru acel nou socket
        if(newSocket < 0){
            exit(1);
        }
        printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
        
        int i=0; 
        if((childpid = fork()) == 0){
            close(sockfd);
            int ok=0;
            char* nume_fisier;
            
            while(1){
                
                recv(newSocket, buffer, 1024, 0);
                if(strcmp(buffer, ":exit") == 0){
                    printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
                    break;

                }else if(strncmp(c1, buffer, strlen(c1))==0 && ok ==0){
                    int lungCom, lungNume;
                    char name[lungNume];
                    lungCom=strlen(buffer); //lungimea comenzii
                    lungNume=lungCom-strlen(c1); //lungimea numelui
                    name[lungNume]='\0';
                    strncpy(name,&buffer[lungCom-lungNume],lungNume);//pun numele din comanda in variabia name
                    printf("\n[copil] asta e numele: %s ", name);
                    printf("\n[copil] %s", w1);
                    if(Search_in_File_name("nume.txt", name)==4){// daca am gasit numele in lista
                        i=i+1;
                        printf("----%d----",i);
                        send(newSocket, v1, strlen(v1), 0);
                        bzero(buffer, sizeof(buffer));      
                        ok=1;
                        printf("\n[copil] am trimis mesajul: %s \n", v1); 
                    }else{ // daca nu am gasit numele in lista
                        send(newSocket, v2, strlen(v2), 0);
                        printf("\n[copil] am trimis mesajul: %s \n", v2); 
                        bzero(buffer, sizeof(buffer));      
                    }
                    
                    
                }else if(strcmp(buffer, "logout")==0 && ok == 1){
                    printf("incercare delogare de la %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
                    printf("delogat de la  %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
                    ok=0;
                    printf("Client: %s\n", buffer);
                    send(newSocket, d1, strlen(d1), 0);
                    bzero(buffer, sizeof(buffer));
                
                }else if(strcmp(buffer, "logout")==0 && ok == 0){
                    printf("incercare delogare de la %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
                    printf("Client: %s\n", buffer);
                    send(newSocket, d2, strlen(d2), 0);
                    bzero(buffer, sizeof(buffer));
                    
                }else if(strcmp(buffer, "cos")==0 && ok == 1){
                    printf("incercare creare cos de la %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
                    printf("Client: %s\n", buffer);
                    printf("----%d---:", ntohs(newAddr.sin_port));
                    //nume_fisier=creare_cos_client(nume_client);
                    //printf("---nume_fisier: %s", nume_fisier);
                    send(newSocket, cos1, strlen(cos1), 0);
                    bzero(buffer, sizeof(buffer));
                    
                        
                }else{
                    printf("Client: %s\n", buffer);
                    send(newSocket, buffer, strlen(buffer), 0);
                    bzero(buffer, sizeof(buffer));
                }
            }
        }

    }

    close(newSocket);


    return 0;
}

如果我在 fork 之前刪除那個“int i=0;”,我的程序可以正常工作,但是一旦我將它添加回來(任何地方),客戶端就無法接受任何輸入,並且服務器不會檢查名稱是否在文件與否。 這就是它凍結的方式

            recv(newSocket, buffer, 1024, 0);
            if(strcmp(buffer, ":exit") == 0){

這里有兩個錯誤:

  1. 您忽略了recv的返回值。 所以你不知道你收到了多少字節。 如果你不知道你有多少數據,你怎么能對一些數據做任何有用的事情呢?

  2. 您只能將 C 風格的字符串傳遞給strcmp 此時, buffer只包含您從對方收到的原始數據。 它不是 C 風格的字符串,因為根據定義,C 風格的字符串有一個終止零字節。

不過,您還有另一個更根本的問題——您對strcmp的使用表明您認為您正在使用消息協議並已收到消息。 但是您使用的是 TCP 和 TCP 不是消息協議。

很難准確地說為什么要添加int i =0; 使您免於崩潰或凍結。 但我的猜測是,零恰好存儲在緩沖區之后的 memory 中,因此幸運的是,它提供了strcmp所需的終止零字節。 但這只是一個猜測。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM