Консольный чат на С/ Ncurses

Недавно решил сделать мини-консольный чат на С + Ncurses, который представляет из себя TCP-server и TCP-client. Если не использовать ncurses сам чат рабоает без проблем, только иногда появляются лишние пробелы на стороне клиента (на удаленном сервере тоже работает). Пробелма заключается в том, что при добавлении ncures функционала, функция get_message программы работает как-то не так. Вроде бы я пробовал записывать что-то в файл, чтобы проверить запускается ли она вообще, так вот она запускается. Не работает именно вывод в чат и именно при получении сообщения от сервера.

TCP-сервер

#include <stdbool.h>
#include <unistd.h>
#include <pthread.h>
#include "../../Utils/Utils.h"
#include "../../Utils/Help.h"

struct AcceptedSocket
{
    int acceptedSocketFD;
    struct sockaddr_in address;
    int error;
    bool acceptedSuccessfully;
};

struct AcceptedSocket * acceptIncomingConnection(int serverSocketFD);
void acceptNewConnectionAndReceiveAndPrintItsData(int serverSocketFD);
void receiveAndPrintIncomingData(int socketFD);

void startAcceptingIncomingConnections(int serverSocketFD);

void receiveAndPrintIncomingDataOnSeparateThread(struct AcceptedSocket *pSocket);

void sendReceivedMessageToTheOtherClients(char *buffer,int socketFD);

struct AcceptedSocket acceptedSockets[10] ;
int acceptedSocketsCount = 0;


void startAcceptingIncomingConnections(int serverSocketFD) {

    while(true)
    {
        struct AcceptedSocket* clientSocket  = acceptIncomingConnection(serverSocketFD);
        acceptedSockets[acceptedSocketsCount++] = *clientSocket;

        receiveAndPrintIncomingDataOnSeparateThread(clientSocket);
    }
}



void receiveAndPrintIncomingDataOnSeparateThread(struct AcceptedSocket *pSocket) {

    pthread_t id;
    pthread_create(&id,NULL,receiveAndPrintIncomingData,pSocket->acceptedSocketFD);
}

void receiveAndPrintIncomingData(int socketFD) {
    char buffer[1024];

    while (true)
    {
        ssize_t  amountReceived = recv(socketFD,buffer,1024,0);

        if(amountReceived>0)
        {
            buffer[amountReceived] = 0;
            printf("%s\n",buffer);

            sendReceivedMessageToTheOtherClients(buffer,socketFD);
        }

        if(amountReceived==0)
            break;
    }

    close(socketFD);
}

void sendReceivedMessageToTheOtherClients(char *buffer,int socketFD) {

    for(int i = 0 ; i<acceptedSocketsCount ; i++)
        if(acceptedSockets[i].acceptedSocketFD !=socketFD)
        {
            send(acceptedSockets[i].acceptedSocketFD,buffer, strlen(buffer),0);
        }

}

struct AcceptedSocket * acceptIncomingConnection(int serverSocketFD) {
    struct sockaddr_in  clientAddress ;
    int clientAddressSize = sizeof (struct sockaddr_in);
    int clientSocketFD = accept(serverSocketFD,&clientAddress,&clientAddressSize);

    struct AcceptedSocket* acceptedSocket = malloc(sizeof (struct AcceptedSocket));
    acceptedSocket->address = clientAddress;
    acceptedSocket->acceptedSocketFD = clientSocketFD;
    acceptedSocket->acceptedSuccessfully = clientSocketFD>0;

    if(!acceptedSocket->acceptedSuccessfully)
        acceptedSocket->error = clientSocketFD;



    return acceptedSocket;
}


int main() {

    int serverSocketFD = createTCPIpv4Socket();
    
    char ip[MAX_IPv4_LENGTH];
    int port;

    get_connection_address(ip, &port);


    struct sockaddr_in *serverAddress = createIPv4Address(ip, port);

    int result = bind(serverSocketFD,serverAddress, sizeof(*serverAddress));
    if(result == 0)
        printf("socket was bound successfully\n");

    int listenResult = listen(serverSocketFD,10);

    startAcceptingIncomingConnections(serverSocketFD);

    shutdown(serverSocketFD,SHUT_RDWR);

    return 0;
}

TCP-клиент

#include <stdbool.h>
#include <unistd.h>
#include <pthread.h>
#include "../../Utils/Utils.h"
#include "../../Utils/Help.h"
#include "../../Graphics/ChatBox.h"


void make_client(int fd);
void* get_message(void* socketPT);
void send_messages(int socketFD, char* name);





    
int main() {

    char ip[MAX_IPv4_LENGTH];
    int port;
    get_connection_address(ip, &port);
    

    int socketFD = createTCPIpv4Socket();
    struct sockaddr_in *address = createIPv4Address(ip, port);

    


    int result = connect(socketFD, (struct sockaddr*)address, sizeof (*address));

    if(result == 0)
        printf("connection was successful\n");


    char name[MAX_NAME_LENGTH];
    get_name(name);


    make_client(socketFD);
    init_interface();
    send_messages(socketFD, name);

    
    close_chat();
    close(socketFD);

    return 0;
}

void send_messages(int socketFD, char* name) {

#if 0
    char *line = NULL;
    size_t lineSize= 0;
    printf("type and we will send(type exit to leave the chat)...\n");

    char buffer[1024];
#endif

    char buffer[1024];
    int length = 0;

    while(true)
    {
        memset(buffer, 0, sizeof(buffer));
        length = 0;
#if 0
        line = NULL;
        ssize_t charCount = getline(&line,&lineSize,stdin);
        line[charCount-1]=0;
        sprintf(buffer,"%s:%s",name , line);

        if(charCount>0)
        {
            if(strcmp(line,"exit")==0)
                break;

            ssize_t amountWasSent =  send(socketFD,
                                          buffer,
                                          strlen(buffer), 0);
        }
#endif 
        int status = read_input(buffer, &length);

        if(status != 1 )
        {
            printf("\n");
            break; 
        }
        buffer[length]= '\0';

        if (length > 0){
            char* self_string = calloc(sizeof(char), length + 10);
            strcat(self_string, "You: ");
            strcat(self_string, buffer);
            add_message(self_string);
            free(self_string);

            char* send_string = calloc(sizeof(char), length + 10);
            strcat(send_string, name);
            strcat(send_string, ": ");
            strcat(send_string, buffer);
            ssize_t amountWasSent =  send(socketFD,
                                          send_string,
                                          strlen(send_string), 0);
            free(send_string);
        }   

    }
}

void make_client(int socketFD) 
{
    pthread_t id ;
    pthread_create(&id, NULL, get_message, (void*)&socketFD);

}

void* get_message(void* socketPT) {
    int socketFD = *(int*)socketPT;

    char buffer[1024];
    while (true)
    {
        ssize_t  amountReceived = recv(socketFD, buffer, 1024, 0);
        add_message(buffer);

        if(amountReceived>0)
        {
            buffer[amountReceived] = 0;
            add_message(buffer);

//          printf("%s\n ",buffer);
        }

        if(amountReceived==0)
            break;
    }

    close(socketFD);
}

файл интерфейса чата

#include <ncurses.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>

#define MSG_CNT 16
#define MSG_LENGTH 256

static WINDOW* info_win;
static WINDOW* msg_win;
static WINDOW* input_win;

char messages[MSG_CNT][MSG_LENGTH];

static void init_info()
{
    info_win = newwin(5, 65, 0, 10);
    box(info_win, 0, 0);
    wrefresh(info_win);
}

static void init_msg()
{
    msg_win = newwin(20, 65, 5, 10);
    box(msg_win, 0 ,0);
    wrefresh(msg_win);
}

static void init_input()
{
    input_win = newwin(4 ,65 ,25 ,10);
    box(input_win , 0 ,0);
    wmove(input_win , 1 ,1);
    wrefresh(input_win);
}

void init_interface()
{
    setlocale(LC_ALL, "");
    initscr();
    cbreak();
    noecho();

    init_info();
    init_msg();
    init_input();

    keypad(input_win ,TRUE);
}

void update_message()
{
    wclear(msg_win);
    box(msg_win ,0 ,0);

    for (int i=0; i<MSG_CNT; i++)
    {
        mvwprintw(msg_win ,i+1 ,1 ,"%s", messages[i]);
    }
    wrefresh(msg_win );
    wmove(input_win , 1 ,1);
    wrefresh(input_win);
}

void add_message(const char* msg)
{
    for (int i=1; i<MSG_CNT; i++)
    {
        memcpy(messages[i-1], messages[i], MSG_LENGTH);
    }
    strncpy(messages[MSG_CNT -1], msg ,MSG_LENGTH -1 );
    messages[MSG_CNT -1][MSG_LENGTH -1] = '\0';
    update_message();
}

int read_input(char *buffer ,int *size)
{
    int symbol;
    while ((symbol=wgetch(input_win)) != ERR)
    {
        if (symbol == '\n')
        {
            if (strncmp(buffer, "/exit", 5) == 0){
                return 2;
            }
            
            mvwprintw(input_win ,1 ,1 ,"%*s" ,*size ,"");
            wrefresh(input_win );
            return 1;
        }
        else if (symbol == KEY_BACKSPACE || symbol ==127)
        {
            if (*size >0)
            {
                (*size)--;
                mvwprintw(input_win ,1 ,*size +1 ," ");
                wmove(input_win ,1 ,*size +1 );
                wrefresh(input_win );
                buffer[*size] = '\0';
            }
        }
        else if (*size < MSG_LENGTH -1)
        {
            buffer[*size] = (char)symbol;
            (*size)++;
            mvwaddch(input_win ,1 ,*size ,"");
            mvwaddch(input_win ,1 ,*size ,symbol );
            wrefresh(input_win );
        }
    }
    return 0;
}

void close_chat()
{
    endwin();
}

Его заголовочный файл

#ifndef CHAT_BOX_H
#define CHAT_BOX_H



void init_interface();
void update_message();
void add_message(const char* msg);
int read_input(char *buffer ,int *size);
void close_chat();



#endif

За остальные файлы я ручаюсь, потому что с ними все работало очень долго. Да и там нет никаких функций влияющих на отправку или получение данных с консоли или чат-интерфейса.

Спасибо за внимание


Ответы (0 шт):