【问题标题】:Socket Programming in C: When client exit server, the server is crashedC中的Socket编程:当客户端退出服务器时,服务器崩溃
【发布时间】:2019-04-05 06:42:52
【问题描述】:

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

客户端.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;
}

服务器.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:

它似乎永远循环“客户端:”而不是显示 printf“断开连接...”的消息,并按我的预期继续与其他客户端一起工作。我在 youtube 上查看此代码,他们可以在视频中正确运行它,但我不知道为什么当我下载此代码并在我的计算机上运行时,它会出现这个问题。谁能帮我解决这个问题,以便服务器可以打印消息“断开连​​接...”。谢谢。

【问题讨论】:

  • 你不应该忽略 recv() 的返回值
  • 另外,TCP套接字没有消息,它们是流,一个send不一定对应一个recv。此外,字符缓冲区不是字符串,sendrecv 不会以空值终止它们。

标签: c sockets


【解决方案1】:

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

Client:
Client:
Client:
Client:

它似乎永远循环“客户端:”而不是显示消息 printf"Disconnected from..." 并继续与其他客户端合作 正如我所料。

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

健壮的服务器代码会检查recv() 调用的返回值,它会返回-1 来表示错误。您的服务器忽略了这一点,只是尝试一次又一次地读取。尽管您不能依赖在客户端消失的每种情况下都会出现错误,但您的服务器不断打印“客户端:”这一事实表明您在这种情况下遇到了错误。

我在 youtube 上查看了这段代码,他们可以在 视频,但我不知道为什么当我下载此代码并在我的 电脑,就出问题了。

要么他们在视频中演示的内容与您展示的代码不同(也许视频在这方面具有欺骗性),要么他们通过输入“:exit”命令退出了客户端,而不仅仅是杀死客户端。

【讨论】:

  • 哦,这是我的错。在视频中,他确实输入了 :exit 来退出客户端而不是 ctrl C。谢谢。
  • @VyTran,如果您的问题得到您满意的回答,那么尽管不是强制性的,但习惯上,通过单击分数左侧的复选标记“接受”您最喜欢的答案.
【解决方案2】:

听起来您的客户端没有正确关闭连接。如果您使用 Ctrl C 停止客户端,那么您正在终止客户端程序而不是中断循环。如果你想以这种方式停止客户端,你应该处理 SIGINT 并关闭套接字连接。

【讨论】:

  • 当客户端终止时,其所有打开的文件,包括套接字,都被操作系统关闭。服务器无限打印“客户端:”的事实表明这确实发生了,因为如果连接仍然打开,没有数据通过,那么recv() 调用将无限期阻塞。
猜你喜欢
  • 1970-01-01
  • 2016-02-29
  • 2015-11-17
  • 1970-01-01
  • 2014-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-10
相关资源
最近更新 更多