在kali linux中运行时出现分门别类故障 - 客户端和服务器聊天室。

问题描述 投票:0回答:1
//server side code
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<stdio.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<errno.h>
#include<string.h>
#include<pthread.h>
#include<sys/types.h>
#include<signal.h>

#define MAX_CLIENTS 100
#define BUFFER_SZ 2048
#define NAME_LEN 32


static int cli_count = 0;
static int uid = 10;

//client structure
typedef struct
{
    struct sockaddr_in address;
    int sockfd;
    int uid;
    char name[NAME_LEN];
} client_t;

client_t *clients[MAX_CLIENTS];

pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;

void str_overwrite_stdout()
{
    printf("\r %s",">");
    fflush(stdout);
}

void str_trim_lf(char* arr, int length)
{
    for(int i=0; i<length; i++)
    {
        if(arr[i] == '\n')
        {
            arr[i] = '\0';
            break;
        }
    }
}

void queue_add(client_t *cl)
{
    pthread_mutex_lock(&clients_mutex);

    for(int i=0; i<MAX_CLIENTS; i++)
    {
        if(!clients[i])
        {
            clients[i] = cl;
            break;
        }
    }

    pthread_mutex_unlock(&clients_mutex);

}

void queue_remove(int uid)
{
    pthread_mutex_lock(&clients_mutex);

    for(int i=0; i<MAX_CLIENTS; i++)
    {
        if(clients[i])
        {
            if(clients[i] -> uid == uid)
            {
                clients[i] = NULL;
                break;
            }
        }
    }

    pthread_mutex_unlock(&clients_mutex);
}
void print_ip_addr(struct sockaddr_in addr)
{
    printf("%d.%d.%d.%d",
    addr.sin_addr.s_addr & 0xff,
    (addr.sin_addr.s_addr & 0xff00) >> 8,
    (addr.sin_addr.s_addr & 0xff0000) >> 16,
    (addr.sin_addr.s_addr & 0xff000000) >> 24);
}

void send_message(char *s, int uid)
{
    pthread_mutex_lock(&clients_mutex);

    for(int i=0; i<MAX_CLIENTS; i++)
    {
        if(clients[i])
        {
            if(clients[i] -> uid != uid)
            {
                if(write(clients[i]->sockfd, s, strlen(s)) < 0)
                {
                    printf("ERROR: write to descriptor failed\n");
                    break;
                }
            }
        }
    }
    pthread_mutex_unlock(&clients_mutex);
}

void *handle_client(void *arg)
{
    char buffer[BUFFER_SZ];
    char name[NAME_LEN];
    int leave_flag = 0;
    cli_count++;

    client_t *cli = (client_t*)arg;

    //name
    if(recv(cli->sockfd, name, NAME_LEN, 0) <= 0 || strlen(name) < 2 || strlen(name) >= NAME_LEN - 1)
    {
        printf("Enter the name: \n");
        leave_flag = 1;
    }
    else
    {
        strcpy(cli->name, name);
        printf(buffer, "%s has joined\n", cli->name);
        printf("%s", buffer);
        send_message(buffer, cli->uid);
    }

    memset(handle_client, BUFFER_SZ, 8*sizeof(name));       //8*sizeof(name)

    while(1)
    {
        if(leave_flag)
        {
            break;
        }

        int receive = recv(cli->sockfd, buffer, BUFFER_SZ, 0);

        if (receive > 0)
        {
            if(strlen(buffer) > 0)
            {
                send_message(buffer, cli->uid);
                str_trim_lf(buffer, strlen(buffer));
                printf("%s\n ", buffer);
            }
        }
        else if (receive == 0 || strcmp(buffer, "exit") == 0)
        {
            sprintf(buffer, "%s has left\n", cli->name);        //sprintf instead of printf
            printf("%s", buffer);
            send_message(buffer, cli->uid);
            leave_flag = 1;
        }
        else
        {
            printf("ERROR: -1\n");
            leave_flag = 1;
        }
        //memset
        memset(handle_client, BUFFER_SZ, 8*sizeof(name));
    }

    close(cli->sockfd);
    queue_remove(cli->uid);
    free(cli);
    cli_count--;
    pthread_detach(pthread_self());

    return NULL;
}

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        printf("usuage: %s <port>\n", argv[0]);
        return EXIT_FAILURE;
    }

    char *ip = "127.0.0.1";
    int port = atoi(argv[1]);

    int option = 1;
    int listenfd = 0, connfd = 0;
    struct sockaddr_in serv_addr;
    struct sockaddr_in cli_addr;
    pthread_t ptid;

    //socket settings
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(ip);
    serv_addr.sin_port = htons(4444);

    //signals
    signal(SIGPIPE, SIG_IGN);

    if(setsockopt(listenfd, SOL_SOCKET, (SO_REUSEPORT | SO_REUSEADDR), (char*)&option, sizeof(option)) < 0)
    {
        printf("ERROR: setsockopt\n");
        return EXIT_FAILURE;
    }

    //bind
    if (bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("ERROR: bind\n");
        return EXIT_FAILURE;
    }

    //listen
    if(listen(listenfd, 10) < 0)
    {
        printf("ERROR: listen\n");
        return EXIT_FAILURE;
    }

    printf(" ----- WELCOME TO THE CHAT SERVER -----\n");

    while(1)
    {
        socklen_t clilen = sizeof(cli_addr);
        connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);

        //check for max client
        if((cli_count + 1) == MAX_CLIENTS)
        {
            printf("Maximum Clients Connected. Connection rejected!");
            print_ip_addr(cli_addr);
            close(connfd);
            continue;
        }

        //client settings
        client_t *cli = (client_t *)malloc(sizeof(client_t));
        cli->address = cli_addr;
        cli->sockfd = connfd;
        cli->uid = uid++;

        //add client to queue
        queue_add(cli);
        pthread_create(&ptid, NULL, &handle_client, (void*)cli);

        //reduce CPU usuage
        sleep(1);

    }

    return EXIT_SUCCESS;

}

//client-side

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

#define MAX_CLIENTS 100
#define BUFFER_SZ 2048
#define NAME_LEN 32

volatile sig_atomic_t flag = 0;
int sockfd = 0;
char name[NAME_LEN];

void str_overwrite_stdout()
{
    printf("\r%s", ">");
    fflush(stdout);
}

void str_trim_lf(char* arr, int length)
{
    for(int i=0; i<length; i++)
    {
        if(arr[i] == '\n')
        {
            arr[i] = '\0';
            break;
        }
    }
 }

 void catch_ctrl_c_and_exit ()
 {
    flag = 1;
 }

 void recv_msg_handler()
 {
    char message[BUFFER_SZ] = {};
    while(1)
    {
        int receive = recv(sockfd, message, BUFFER_SZ, 0);

        if(receive > 0)
        {
            printf("%s", message);
            str_overwrite_stdout();
        }
        else if(receive == 0)
        {
            break;
        }
        memset(message, BUFFER_SZ, 1); // memeset
    }
 }

 void send_msg_handler()
 {
    char buffer[BUFFER_SZ] = {};
    char message[BUFFER_SZ + NAME_LEN] = {};

    while(1)
    {
        str_overwrite_stdout();
        fgets(buffer, BUFFER_SZ, stdin);
        str_trim_lf(buffer, BUFFER_SZ);

        if(strcmp(buffer, "exit") == 0)
        {
            break;
        }
        else
        {
            sprintf(message, "%s: %s\n", name, buffer);
            send(sockfd, message, strlen(message), 0);
        }
        memset(buffer, BUFFER_SZ, 1);               //memset
        memset(message, BUFFER_SZ + NAME_LEN, 1);   //memset
    }
    catch_ctrl_c_and_exit(2);
 }

 int main(int argc, char **argv)
 {
    if(argc != 2)
    {
        printf("Usuage: %s <port>\n", argv[0]);
        return EXIT_FAILURE;
    }

    char *ip = "127.0.0.1";
    int port = atoi(argv[1]);

    signal(SIGINT, catch_ctrl_c_and_exit);

    printf("Enter your name: \n");
    fgets(name, NAME_LEN, stdin);
    str_trim_lf(name, strlen(name));

    if(strlen(name) > NAME_LEN - 1 || strlen(name) < 2)
    {
        printf("Enter the name correctly");
        return EXIT_FAILURE;
    }

    struct sockaddr_in toserver;

    //socket settings
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    toserver.sin_family = AF_INET;
    toserver.sin_addr.s_addr = inet_addr(ip);
    toserver.sin_port = htons(4444);

    //connect client to server
    int err = connect(sockfd, (struct sockaddr*)&toserver, sizeof(toserver));
    if (err == -1)
    {
        printf("ERROR: connect\n");
        return EXIT_FAILURE;
    }

    //send the name
    send(sockfd, name, NAME_LEN, 0);

    printf("--- WELCOME TO CHAT SERVER ---\n");

    pthread_t  send_msg_thread;
    if(pthread_create(&send_msg_thread, NULL, (void*)send_msg_handler, NULL) != 0)
    {
        printf("ERROR: pthread\n");
        return EXIT_FAILURE;
    }

    pthread_t  recv_msg_thread;
    if(pthread_create(&recv_msg_thread, NULL, (void*)recv_msg_handler, NULL) != 0)
    {
        printf("ERROR: pthread\n");
        return EXIT_FAILURE;
    }

    while(1)
    {
        if(flag)
        {
            printf("\n BYE \n");
            break;
        }
    }

    close(sockfd);

    return EXIT_SUCCESS;
 }

我一直在尝试运行这段代码,但每次在说欢迎来到聊天服务器后都会出现分段错误,有谁能帮我解决这个问题吗.要运行我用的是GCC。

这段代码实际上是想把从客户端收到的消息广播出去,然后发送给所有其他加入服务器的客户端。

c sockets fork
1个回答
1
投票

这一行有问题。

memset(handle_client, BUFFER_SZ, 8*sizeof(name));

你在传递函数指针作为第一个参数。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.