C语言中的套接字编程:客户端退出服务器时,服务器崩溃了

时间:2018-11-01 02:42:47

标签: c sockets

我运行一个套接字编程代码,用于多个客户端与一台服务器的通信。一切正常,但是当我按C Ctrl C退出客户端之一时,服务器未按预期显示。下面是代码:

Client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 4444

int main(){

    int clientSocket, ret;
    struct sockaddr_in serverAddr;
    char buffer[1024];

    clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if(clientSocket < 0){
        printf("[-]Error in connection.\n");
        exit(1);
     }
     printf("[+]Client 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 = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if(ret < 0){
         printf("[-]Error in connection.\n");
         exit(1);
     }
     printf("[+]Connected to Server.\n");

     while(1){
        printf("Client: \t");
        scanf("%s", &buffer[0]);
        send(clientSocket, buffer, strlen(buffer), 0);

        if(strcmp(buffer, ":exit") == 0){
            close(clientSocket);
            printf("[-]Disconnected from server.\n");
            exit(1);
        }

        if(recv(clientSocket, buffer, 1024, 0) < 0){
            printf("[-]Error in receiving data.\n");
        }else{
            printf("Server: \t%s\n", buffer);
        }
    }

    return 0;
}

Server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 4444

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));
    if(ret < 0){
        printf("[-]Error in binding.\n");
        exit(1);
    }
    printf("[+]Bind to port %d\n", 4444);

    if(listen(sockfd, 10) == 0){
        printf("[+]Listening....\n");
    }else{
        printf("[-]Error in binding.\n");
    }


    while(1){
        newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
        if(newSocket < 0){
            exit(1);
        }
        printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));

        if((childpid = fork()) == 0){
            close(sockfd);

            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{
                    printf("Client: %s\n", buffer);
                    send(newSocket, buffer, strlen(buffer), 0);
                    bzero(buffer, sizeof(buffer));
                }
            }
        }

     }

    close(newSocket);


    return 0;
}

当我按ctrl C退出客户端时。在服务器端,它显示:

Client:
Client:
Client:
Client:

,它似乎永远循环“ Client:”,而不是显示printf“ Disconnected from ...”的消息,并继续与我期望的其他客户端一起工作。我在youtube上查看了这些代码,他们可以在视频中正常运行它,但是我不知道为什么当我下载此代码并在计算机上运行时会出现此问题。任何人都可以帮助我解决该问题,以便服务器可以打印消息“ Disconnection ...”。谢谢。

2 个答案:

答案 0 :(得分:1)

听起来您的客户端未正确关闭连接。如果您使用Ctrl C停止客户端,那么您正在杀死客户端程序并且没有中断循环。如果要这样停止客户端,则应处理SIGINT并关闭套接字连接。

答案 1 :(得分:1)

  

当我按ctrl C退出客户端时。在服务器端,它显示:

Client:
Client:
Client:
Client:
     

,似乎永远循环“ Client:”,而不显示消息   printf“与...断开连接”,并继续与其他客户端一起使用   如我所料。

您的代码仅在收到来自客户端的“:exit”消息时才打印断开连接消息并退出循环。如果您使用Ctrl-C杀死客户端,则它将终止而不发送任何此类消息。

严格的服务器代码将检查recv()调用的返回值,该返回值将返回-1表示错误。您的服务器将忽略该内容,而仅尝试一次又一次地读取。尽管您不能在每次客户端消失的情况下都得到错误提示,但是服务器不断打印“ Client:”这一事实表明在这种情况下您将获得错误提示。

  

我在youtube上查看了这段代码,他们可以在   视频,但我不知道为什么下载此代码并在我的计算机上运行   电脑,就解决了这个问题。

他们在视频中展示的内容与您提供的代码不同(也许视频对此具有欺骗性),或者他们通过键入“:exit”命令退出了客户端,而不仅仅是杀死了客户端。 / p>